This document aims at exploring the dataset of 4 individuals in 2018. For that purpose, we need first to load the weanlingNES package to load data.
# load library
library(weanlingNES)
# load data
data("data_nes", package = "weanlingNES")
# load("../data/data_nes.rda")
Let’s have a look at what’s inside data_nes$data_2018:
# list structure
str(data_nes$year_2018, max.level = 1, give.attr = F, no.list = T)
## $ ind_2018070:Classes 'data.table' and 'data.frame': 22393 obs. of 47 variables:
## $ ind_2018072:Classes 'data.table' and 'data.frame': 29921 obs. of 47 variables:
## $ ind_2018074:Classes 'data.table' and 'data.frame': 38608 obs. of 47 variables:
## $ ind_2018080:Classes 'data.table' and 'data.frame': 19028 obs. of 47 variables:
A list of 4 data.frames, one for each seal
For convenience, we aggregate all 4 individuals into one dataset.
# combine all individuals
data_2018 <- rbindlist(data_nes$year_2018)
# display
DT::datatable(data_2018[sample.int(.N, 10), ], options = list(scrollX = T))
Table 1: Sample of 10 random rows from data_2018
Summary
# raw_data
data_2018[, .(
nb_days_recorded = uniqueN(as.Date(date)),
nb_dives = .N,
maxdepth_mean = mean(maxdepth),
dduration_mean = mean(dduration),
botttime_mean = mean(botttime),
pdi_mean = mean(pdi, na.rm = T)
), by = .id] %>%
sable(
caption = "Summary diving information relative to each 2018 individual",
digits = 2
)
Table 2: Summary diving information relative to each 2018 individual
|
.id
|
nb_days_recorded
|
nb_dives
|
maxdepth_mean
|
dduration_mean
|
botttime_mean
|
pdi_mean
|
|
ind_2018070
|
232
|
22393
|
305.52
|
783.27
|
243.22
|
109.55
|
|
ind_2018072
|
341
|
29921
|
357.86
|
876.96
|
278.02
|
104.90
|
|
ind_2018074
|
372
|
38608
|
250.67
|
686.25
|
291.89
|
302.77
|
|
ind_2018080
|
215
|
19028
|
296.50
|
867.69
|
339.90
|
103.51
|
Very nice dataset :)
Some explanatory plots
Missing values
# build dataset to check for missing values
dataPlot <- melt(data_2018[, .(.id, is.na(.SD)), .SDcol = -c(
".id",
"divenumber",
"year",
"month",
"day",
"hour",
"min",
"sec",
"juldate",
"divetype",
"date",
"phase",
"lat",
"lon"
)])
# add the id of rows
dataPlot[, id_row := c(1:.N), by = c("variable", ".id")]
# plot
ggplot(dataPlot, aes(x = variable, y = id_row, fill = value)) +
geom_tile() +
labs(x = "Attributes", y = "Rows") +
scale_fill_manual(
values = c("white", "black"),
labels = c("Real", "Missing")
) +
facet_wrap(.id ~ ., scales = "free_y") +
theme_jjo() +
theme(
legend.position = "top",
axis.text.x = element_text(angle = 45, hjust = 1),
legend.key = element_rect(colour = "black")
)
So far so good, only few variables seems to have missing values:
# table with percent
table_inter <- data_2018[, lapply(.SD, function(x) {
round(length(x[is.na(x)]) * 100 / length(x), 1)
}), .SDcol = -c(
".id",
"divenumber",
"year",
"month",
"day",
"hour",
"min",
"sec",
"juldate",
"divetype",
"date",
"phase",
"lat",
"lon"
)]
# find which are different from 0
cond_inter <- sapply(table_inter, function(x) {
x == 0
})
# display the percentages that are over 0
table_inter[, which(cond_inter) := NULL] %>%
sable(caption = "Percentage of missing values per columns having missing values!") %>%
scroll_box(width = "100%")
Table 3: Percentage of missing values per columns having missing values!
|
lightatsurf
|
lattenuation
|
euphoticdepth
|
thermoclinedepth
|
driftrate
|
benthicdivevertrate
|
cornerindex
|
foragingindex
|
verticalspeed90perc
|
verticalspeed95perc
|
dist_dep
|
|
26.3
|
89
|
62.6
|
1.3
|
0.5
|
22.7
|
75.8
|
0.5
|
0.1
|
0.1
|
35.1
|
Outliers
Ok, let’s have a look at all the data. But first, we have to remove outliers. Some of them are quiet easy to spot looking at the distribution of dive duration:
Before
ggplot(
data_2018[, .SD][, state := "Before"],
aes(x = dduration, fill = .id)
) +
geom_histogram(show.legend = FALSE) +
geom_vline(xintercept = 3000, linetype = "longdash") +
facet_grid(state ~ .id,
scales = "free"
) +
labs(y = "# of dives", x = "Dive duration (s)") +
theme_jjo()
After
ggplot(
data_2018[dduration < 3000, ][][, state := "After"],
aes(x = dduration, fill = .id)
) +
geom_histogram(show.legend = FALSE) +
geom_vline(xintercept = 3000, linetype = "longdash") +
facet_grid(state ~ .id,
scales = "free"
) +
labs(x = "# of dives", y = "Dive duration (s)") +
theme_jjo()
It seems much better, so let’s remove any rows with dduration > 3000 sec.
# filter data
data_2018_filter <- data_2018[dduration < 3000, ]
# nbrow removed
data_2018[dduration >= 3000, .(nb_row_removed = .N), by = .id] %>%
sable(caption = "# of rows removed by 2018-individuals")
Table 4: # of rows removed by 2018-individuals
|
.id
|
nb_row_removed
|
|
ind_2018070
|
3
|
|
ind_2018072
|
1
|
|
ind_2018074
|
33
|
Check day and night
Light levels
# let's first average `lightatsurf` by individuals, day since departure and hour
dataPlot <- data_2018[, .(lightatsurf = median(lightatsurf)),
by = .(.id, day_departure, date = as.Date(date), hour)
]
# display the result
ggplot(dataPlot, aes(x = day_departure, y = hour, fill = lightatsurf)) +
geom_tile() +
facet_grid(.id ~ .) +
theme_jjo() +
labs(x = "# of days since departure",
y = "Hour",
fill = "Light level at the surface")+
theme(legend.position = c("bottom"))
Day and night detection
# let's first average `lightatsurf` by individuals, day since departure and hour
dataPlot <- data_2018[, .(lightatsurf = median(lightatsurf)),
by = .(.id,
day_departure,
date = as.Date(date),
hour,
phase)
]
# display the result
ggplot(dataPlot, aes(x = day_departure, y = hour, fill = phase)) +
geom_tile() +
facet_grid(.id ~ .) +
theme_jjo() +
labs(x = "# of days since departure",
y = "Hour",
fill = "Day time and night time as detected by the `cal_phase_day` function") +
theme(legend.position = c("bottom"))
All Variables
names_display <- names(data_2018_filter[, -c(
".id",
"date",
"divenumber",
"year",
"month",
"day",
"hour",
"min",
"sec",
"juldate",
"divetype",
"euphoticdepth",
"thermoclinedepth",
"day_departure",
"phase",
"lat",
"lon",
"dist_dep"
)])
for (i in names_display) {
cat("#####", i, "{.unlisted .unnumbered} \n")
if (i == "maxdepth") {
print(
ggplot() +
geom_point(
data = data_2018_filter[, .(
.id,
date,
thermoclinedepth
)],
aes(
x = as.Date(date),
y = -thermoclinedepth,
colour = "Thermocline (m)"
),
alpha = .2,
size = .5
) +
geom_point(
data = data_2018_filter[, .(
.id,
date,
euphoticdepth
)],
aes(
x = as.Date(date),
y = -euphoticdepth,
colour = "Euphotic (m)"
),
alpha = .2,
size = .5
) +
scale_colour_manual(
values = c(
"Thermocline (m)" = "red",
"Euphotic (m)" = "black"
),
name = "Zone"
) +
new_scale_color() +
geom_point(
data = melt(data_2018_filter[, .(.id, date, get(i))],
id.vars = c(".id", "date")),
aes(
x = as.Date(date),
y = -value,
col = .id
),
alpha = 1 / 10,
size = .5,
show.legend = FALSE
) +
facet_wrap(. ~ .id, scales = "free") +
scale_x_date(date_labels = "%m/%Y") +
labs(x = "Date", y = "Maximum Depth (m)") +
theme_jjo() +
theme(
axis.text.x = element_text(angle = 45, hjust = 1),
legend.position = "bottom"
)
)
cat("<blockquote> Considering `ind_2018074` has slightly different values than other individuals for the thermocline depth, it would be interesting to see where the animal went. </blockquote>")
} else if (i == "driftrate") {
print(
ggplot(
data = melt(data_2018_filter[, .(.id, date, get(i), divetype)],
id.vars = c(".id", "date", "divetype")),
aes(
x = as.Date(date),
y = value,
col = divetype
)
) +
geom_point(
alpha = 1 / 10,
size = .5
) +
facet_wrap(. ~ .id, scales = "free") +
scale_x_date(date_labels = "%m/%Y") +
labs(x = "Date", y = "Drift Rate 'm/s", col = "Dive Type") +
theme_jjo() +
theme(
axis.text.x = element_text(angle = 45, hjust = 1),
legend.position = "bottom"
) +
guides(colour = guide_legend(override.aes = list(
size = 7,
alpha = 1
)))
)
} else {
print(
ggplot(
data = melt(data_2018_filter[, .(.id, date, get(i))],
id.vars = c(".id", "date")),
aes(
x = as.Date(date),
y = value,
col = .id
)
) +
geom_point(
show.legend = FALSE,
alpha = 1 / 10,
size = .5
) +
facet_wrap(. ~ .id, scales = "free") +
scale_x_date(date_labels = "%m/%Y") +
labs(x = "Date", y = i) +
theme_jjo() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
)
}
cat("\n \n")
}
maxdepth
Considering ind_2018074 has slightly different values than other individuals for the thermocline depth, it would be interesting to see where the animal went.
dduration

botttime

desctime

descrate

asctime

ascrate

pdi

dwigglesdesc

dwigglesbott

dwigglesasc

totvertdistbot

bottrange

efficiency

idz

lightatbott

lwiggles

lightatsurf

lattenuation

tempatsurf

tempatbott

driftdiveindex

driftrate

benthicdiveindex

benthicdivevertrate

cornerindex

foragingindex

verticalspeed90perc

verticalspeed95perc

Few questions, that I should look into it:
- is the bimodal distribution of
dduration, desctime due to nycthemeral migration?
- is the bimodal distribution of
descrate (especially for ind2018070 and ind_2018072) due to drift dive?
- is
lightatbott could be used to identify bioluminescence, cause it seems there is a lot going on at the bottom?
- are the variations observed for
lightatsurf is due to moon cycle?
- not sure why is there a bimodal distribution of
tempatbott!
drifrate that one is awesome! Thanks to divetype we can clearly see a pattern of how driftrate (and so buoyancy) change according time.
- the bimodal distribution of
verticalspeed90 and verticalspeed95 should be due to drift dive.
# same plot with a colored for the phase of the day
for (i in names_display) {
cat("####", i, "{-} \n")
print(
ggplot(
data = melt(data_2018_filter[, .(.id, date, get(i), phase)],
id.vars = c(
".id",
"date",
"phase"
)
),
aes(
x = as.Date(date),
y = value,
col = phase
)
) +
geom_point(
alpha = 1 / 10,
size = .5
) +
facet_wrap(. ~ .id, scales = "free") +
scale_x_date(date_labels = "%m/%Y") +
labs(x = "Date", y = i) +
theme_jjo() +
theme(
axis.text.x = element_text(angle = 45, hjust = 1),
legend.position = "bottom"
) +
guides(colour = guide_legend(override.aes = list(
size = 7,
alpha = 1
)))
)
cat("\n \n")
}
maxdepth

dduration

botttime

desctime

descrate

asctime

ascrate

pdi

dwigglesdesc

dwigglesbott

dwigglesasc

totvertdistbot

bottrange

efficiency

idz

lightatbott

lwiggles

lightatsurf

lattenuation

tempatsurf

tempatbott

driftdiveindex

driftrate

benthicdiveindex

benthicdivevertrate

cornerindex

foragingindex

verticalspeed90perc

verticalspeed95perc

All Variables during the first month
for (i in names_display) {
cat("####", i, "{.unlisted .unnumbered} \n")
if (i == "maxdepth") {
print(
ggplot() +
geom_point(
data = data_2018_filter[day_departure < 32, .(
.id,
day_departure,
thermoclinedepth
)],
aes(
x = day_departure,
y = -thermoclinedepth,
colour = "Thermocline (m)",
group = day_departure
),
alpha = .2,
size = .5
) +
geom_point(
data = data_2018_filter[day_departure < 32, .(
.id,
day_departure,
euphoticdepth
)],
aes(
x = day_departure,
y = -euphoticdepth,
colour = "Euphotic (m)",
group = day_departure
),
alpha = .2,
size = .5
) +
scale_colour_manual(
values = c(
"Thermocline (m)" = "red",
"Euphotic (m)" = "black"
),
name = "Zone"
) +
new_scale_color() +
geom_boxplot(
data = melt(data_2018_filter[day_departure < 32,
.(.id, day_departure, get(i))],
id.vars = c(".id", "day_departure")),
aes(
x = day_departure,
y = -value,
col = .id,
group = day_departure
),
alpha = 1 / 10,
size = .5,
show.legend = FALSE
) +
facet_wrap(. ~ .id, scales = "free") +
labs(x = "# days since departure", y = "Maximum Depth (m)") +
theme_jjo() +
theme(legend.position = "bottom")
)
} else {
print(
ggplot(
data = melt(data_2018_filter[day_departure < 32,
.(.id, day_departure, get(i))],
id.vars = c(".id", "day_departure")),
aes(
x = day_departure,
y = value,
color = .id,
group = day_departure
)
) +
geom_boxplot(
show.legend = FALSE,
alpha = 1 / 10,
size = .5
) +
facet_wrap(. ~ .id, scales = "free") +
labs(x = "# days since departure", y = i) +
theme_jjo()
)
}
cat("\n \n")
}
maxdepth

dduration

botttime

desctime

descrate

asctime

ascrate

pdi

dwigglesdesc

dwigglesbott

dwigglesasc

totvertdistbot

bottrange

efficiency

idz

lightatbott

lwiggles

lightatsurf

lattenuation

tempatsurf

tempatbott

driftdiveindex

driftrate

benthicdiveindex

benthicdivevertrate

cornerindex

foragingindex

verticalspeed90perc

verticalspeed95perc

for (i in names_display) {
cat("####", i, "{.unlisted .unnumbered} \n")
print(
ggplot(
data = melt(data_2018_filter[
day_departure < 32,
.(.id, day_departure, get(i), phase)
],
id.vars = c(".id", "day_departure", "phase")
),
aes(
x = day_departure,
y = value,
color = phase,
group = interaction(day_departure, phase),
)
) +
geom_boxplot(
alpha = 1 / 10,
size = .5
) +
facet_wrap(. ~ .id, scales = "free") +
labs(x = "# days since departure", y = i) +
theme_jjo() +
theme(legend.position = "bottom")
)
cat("\n \n")
}
maxdepth

dduration

botttime

desctime

descrate

asctime

ascrate

pdi

dwigglesdesc

dwigglesbott

dwigglesasc

totvertdistbot

bottrange

efficiency

idz

lightatbott

lwiggles

lightatsurf

lattenuation

tempatsurf

tempatbott

driftdiveindex

driftrate

benthicdiveindex

benthicdivevertrate

cornerindex

foragingindex

verticalspeed90perc

verticalspeed95perc

Correlation
Can we find nice correlation?
# compute correlation
corr_2018 <- round(cor(data_2018_filter[, names_display, with = F],
use = "pairwise.complete.obs"
), 1)
# replace NA value by 0
corr_2018[is.na(corr_2018)] <- 0
# compute p_values
corr_p_2018 <- cor_pmat(data_2018_filter[, names_display, with = F])
# replace NA value by 0
corr_p_2018[is.na(corr_p_2018)] <- 1
# display
ggcorrplot(
corr_2018,
p.mat = corr_p_2018,
hc.order = TRUE,
method = "circle",
type = "lower",
ggtheme = theme_jjo(),
sig.level = 0.05,
colors = c("#00AFBB", "#E7B800", "#FC4E07")
)
Another way to see it:
# flatten correlation matrix
cor_result_2018 <- flat_cor_mat(corr_2018, corr_p_2018)
# keep only the one above .7
cor_result_2018[cor >= .7, ][order(-abs(cor))] %>%
sable(caption = "Pairwise correlation above 0.75 and associated p-values")
Table 5: Pairwise correlation above 0.75 and associated p-values
|
row
|
column
|
cor
|
p
|
|
verticalspeed90perc
|
verticalspeed95perc
|
1.0
|
0
|
|
maxdepth
|
asctime
|
0.8
|
0
|
|
botttime
|
efficiency
|
0.8
|
0
|
|
dwigglesbott
|
foragingindex
|
0.8
|
0
|
|
maxdepth
|
dduration
|
0.7
|
0
|
|
maxdepth
|
desctime
|
0.7
|
0
|
|
dduration
|
desctime
|
0.7
|
0
|
|
dduration
|
asctime
|
0.7
|
0
|
|
totvertdistbot
|
bottrange
|
0.7
|
0
|
|
totvertdistbot
|
verticalspeed90perc
|
0.7
|
0
|
|
totvertdistbot
|
verticalspeed95perc
|
0.7
|
0
|
I guess nothing unexpected here, I’ll have to check with Patrick about the efficiency ;)
Dive Type
# dataset to plot proportional area plot
data_2018_filter[, sum_id := .N, by = .(.id, day_departure)] %>%
.[, sum_id_days := .N, by = .(.id, day_departure, divetype)] %>%
.[, prop := sum_id_days / sum_id]
dataPlot <- unique(data_2018_filter[, .(prop, .id, divetype, day_departure)])
# area plot
ggplot(dataPlot, aes(
x = as.numeric(day_departure),
y = prop,
fill = as.character(divetype)
)) +
geom_area(alpha = 0.6, size = 1) +
facet_wrap(.id ~ ., scales = "free") +
theme_jjo() +
theme(legend.position = "bottom") +
labs(x = "# of days since departure",
y = "Proportion of dives",
fill = "Dive types")
Dive duration vs. Maximum depth
Colored by ID
# plot
ggplot(data = data_2018_filter, aes(y = dduration, x = maxdepth, col = .id)) +
geom_point(size = .5, alpha = .1, show.legend = FALSE) +
facet_wrap(.id ~ .) +
labs(x = "Maximum depth (m)", y = "Dive duration (s)") +
theme_jjo()
Colored by Dive Type
# plot
ggplot(data = data_2018_filter, aes(y = dduration,
x = maxdepth,
col = divetype)) +
geom_point(size = .5, alpha = .1) +
facet_wrap(.id ~ .) +
guides(colour = guide_legend(override.aes = list(size = 5, alpha = 1))) +
labs(x = "Maximum depth (m)", y = "Dive duration (s)") +
theme_jjo() +
theme(legend.position = "bottom")
Colored by # days since departure
# plot
ggplot(data = data_2018_filter[, prop_track := (day_departure * 100) / max(day_departure), by = .id],
aes(y = dduration, x = maxdepth, col = prop_track)) +
geom_point(size = .5, alpha = .1) +
facet_wrap(.id ~ .) +
labs(x = "Maximum depth (m)",
y = "Dive duration (s)",
col = "Proportion of completed track (%)") +
scale_color_continuous(type = "viridis") +
theme_jjo() +
theme(legend.position = "bottom")
Colored by phases of day
# plot
ggplot(data = data_2018_filter, aes(y = dduration, x = maxdepth, col = phase)) +
geom_point(size = .5, alpha = .1) +
facet_wrap(.id ~ .) +
guides(colour = guide_legend(override.aes = list(size = 5, alpha = 1))) +
labs(x = "Maximum depth (m)",
y = "Dive duration (s)",
col = "Phases of the day") +
theme_jjo() +
theme(legend.position = "bottom")
There seems to be a patch for high depths (especially visible for ind2018070), but I don’t know what it could be linked to…
Drift Rate
In the following graphs:
driftrate is calculated using only divetype == "2: drift"
- whereas all the others variables are calculated all dives considered
# build dataset
dataPlot <- data_2018_filter[divetype == "2: drift",
# median drift rate for drift dive
.(driftrate = median(driftrate, na.rm = T)),
by = .(.id, day_departure)
][data_2018_filter[,
.(
# median dive duration all dives considered
dduration = median(dduration, na.rm = T),
# median max depth all dives considered
maxdepth = median(maxdepth, na.rm = T),
# median bottom dives all dives considered
botttime = median(botttime, na.rm = T)
),
by = .(.id, day_departure)
],
on = c(".id", "day_departure")
]
# plot
ggplot(dataPlot, aes(x = botttime, y = driftrate, col = .id)) +
geom_point(size = .5, alpha = .5) +
geom_smooth(method = "lm") +
guides(color = "none") +
facet_wrap(.id ~ .) +
scale_x_continuous(limits = c(0, 700)) +
labs(x = "Daily median Bottom time (s)",
y = "Daily median drift rate (m.s-1)") +
theme_jjo()
# plot
ggplot(dataPlot, aes(x = maxdepth, y = driftrate, col = .id)) +
geom_point(size = .5, alpha = .5) +
geom_smooth(method = "lm") +
guides(color = "none") +
facet_wrap(.id ~ .) +
labs(x = "Daily median Maximum depth (m)",
y = "Daily median drift rate (m.s-1)") +
theme_jjo()
# plot
ggplot(dataPlot, aes(x = dduration, y = driftrate, col = .id)) +
geom_point(size = .5, alpha = .5) +
geom_smooth(method = "lm") +
guides(color = "none") +
facet_wrap(.id ~ .) +
labs(x = "Daily median Dive duration (s)",
y = "Daily median drift rate (m.s-1)") +
theme_jjo()
Behavioral Aerobic Dive Limit (bADL)
# dive duration vs pdi by days
ggplot(data = data_2018_filter[pdi < 300, ], aes(
x = dduration,
y = pdi,
color = .id,
group = dduration,
fill = "none"
)) +
geom_boxplot(show.legend = FALSE, outlier.alpha = 0.05, alpha = 0) +
labs(x = "Dive duration (s)", y = "Post-dive duration (s)") +
facet_wrap(. ~ .id, scales = "free_x") +
theme_jjo()
# dive duration vs pdi by days
ggplot(data = data_2018_filter[pdi < 300,], aes(x = dduration,
y = pdi,
color = .id)) +
geom_point(show.legend = FALSE, alpha = 0.05) +
geom_smooth(
method = "gam",
show.legend = FALSE,
col = "black",
linetype = "dashed"
) +
labs(x = "Dive duration (s)", y = "Post-dive duration (s)") +
facet_wrap(. ~ .id, scales = "free_x") +
theme_jjo()
# dive duration vs pdi by days
ggplot(
data = data_2018_filter[pdi < 300, .(.id, pdi_ratio = pdi / dduration, day_departure)],
aes(
x = day_departure,
y = pdi_ratio,
color = .id,
group = day_departure,
fill = "none"
)
) +
geom_boxplot(show.legend = FALSE,
outlier.alpha = 0.05,
alpha = 0) +
labs(x = "# days since departure", y = "Post-dive / Dive duration ratio") +
facet_wrap(. ~ .id, scales = "free_x") +
# zoom
coord_cartesian(ylim = c(0, 0.4)) +
theme_jjo()
Based on Shero et al. (2018), we decided to look at the bADL as the 95th percentile of dive duration each day, for those with \(n \geq 50\). This threshold was chosen following this figure:
ggplot(data_2018_filter[,.(nb_dives = .N),
by = .(.id, day_departure)],
aes(x=nb_dives, fill=.id)) +
geom_histogram(show.legend = FALSE) +
facet_grid(.~.id) +
labs(y="# of days", x = "# of dives per day") +
theme_jjo()
# select day that have at least 50 dives
days_to_keep = data_2018_filter[,
.(nb_dives = .N),
by = .(.id, day_departure)] %>%
.[nb_dives >= 50,]
# keep only those days
data_2018_filter_complete_day = merge(data_2018_filter,
days_to_keep,
by = c(".id", "day_departure"))
# data plot
dataPlot = data_2018_filter_complete_day[,
.(badl = quantile(dduration, 0.95)),
by = .(.id, day_departure)]
# combine two datasets to be able to use a second axis
# https://stackoverflow.com/questions/49185583/two-y-axes-with-different-scales-for-two-datasets-in-ggplot2
dataMegaPlot = rbind(data_2018_filter_complete_day[divetype == "2: drift"] %>%
.[, .(w = .id,
y = driftrate,
x = day_departure,
z = "second_plot")],
dataPlot[, .(
w = .id,
# tricky one
y = (badl / 1000) - 1,
x = day_departure,
z = "first_plot"
)])
# plot
ggplot() +
geom_point(
data = dataMegaPlot[z == "second_plot", ],
aes(x = x, y = y),
alpha = 1 / 10,
size = 0.5,
color = "grey40",
show.legend = FALSE
) +
geom_path(data = dataMegaPlot[z == "first_plot", ],
aes(x = x, y = y, color = w),
show.legend = FALSE) +
scale_y_continuous(
# Features of the first axis
name = "Drift rate (m/s)",
# Add a second axis and specify its features
sec.axis = sec_axis( ~ (. * 1000) + 1000,
name = "Behavioral Aerobic Dive Limit (s)")
) +
labs(x = "# days since departure") +
facet_wrap(w ~ .) +
theme_jjo()
Looking at this graph, I want to believe that there is some kind of relationship between the bADL as defined by Shero et al. (2018) and the drift rate (and so buyoancy).
# get badl
dataplot_1 = data_2018_filter_complete_day[,
.(badl = quantile(dduration, 0.95)),
by = .(.id, day_departure)]
# get driftrate
dataplot_2 = data_2018_filter_complete_day[divetype == "2: drift",
.(driftrate = median(driftrate)),
by = .(.id, day_departure)]
# merge
dataPlot = merge(dataplot_1,
dataplot_2,
by = c(".id", "day_departure"),
all = TRUE)
# plot
ggplot(data = dataPlot, aes(x = badl, y = driftrate, col = .id)) +
geom_point(show.legend = FALSE) +
facet_wrap(.id~., scales = "free") +
theme_jjo()

ind_2018070
# ind_2018070
plot_ly(
x = dataPlot[.id == "ind_2018070", badl],
y = dataPlot[.id == "ind_2018070", day_departure],
z = dataPlot[.id == "ind_2018070", driftrate],
type = "scatter3d",
mode = "markers",
marker = list(size = 2),
color = dataPlot[.id == "ind_2018070", day_departure]
) %>%
layout(scene = list(xaxis = list(title = 'Behavioral ADL'),
yaxis = list(title = '# days since departure'),
zaxis = list(title = 'Drift rate (m/s)')))
ind_2018072
# ind_2018072
plot_ly(
x = dataPlot[.id == "ind_2018072", badl],
y = dataPlot[.id == "ind_2018072", day_departure],
z = dataPlot[.id == "ind_2018072", driftrate],
type = "scatter3d",
mode = "markers",
marker = list(size = 2),
color = dataPlot[.id == "ind_2018072", day_departure]
) %>%
layout(scene = list(xaxis = list(title = 'Behavioral ADL'),
yaxis = list(title = '# days since departure'),
zaxis = list(title = 'Drift rate (m/s)')))
ind_2018074
# ind_2018074
plot_ly(
x = dataPlot[.id == "ind_2018074", badl],
y = dataPlot[.id == "ind_2018074", day_departure],
z = dataPlot[.id == "ind_2018074", driftrate],
type = "scatter3d",
mode = "markers",
marker = list(size = 2),
color = dataPlot[.id == "ind_2018074", day_departure]
) %>%
layout(scene = list(xaxis = list(title = 'Behavioral ADL'),
yaxis = list(title = '# days since departure'),
zaxis = list(title = 'Drift rate (m/s)')))
ind_2018072
# ind_2018080
plot_ly(
x = dataPlot[.id == "ind_2018080", badl],
y = dataPlot[.id == "ind_2018080", day_departure],
z = dataPlot[.id == "ind_2018080", driftrate],
type = "scatter3d",
mode = "markers",
marker = list(size = 2),
color = dataPlot[.id == "ind_2018080", day_departure]
) %>%
layout(scene = list(xaxis = list(title = 'Behavioral ADL'),
yaxis = list(title = '# days since departure'),
zaxis = list(title = 'Drift rate (m/s)')))
GPS data
Since this part is time consuming, we dedicated a whole article (vignette("data_exploration_2018_map")) to reduce compilation time.
# saving the data_2018_filter dataset
saveRDS(data_2018_filter, file = "tmp/data_2018_filter.rds")
LS0tCnRpdGxlOiAiRGF0YSBFeHBsb3JhdGlvbiAtIDIwMTgiCmF1dGhvcjogIkpvZmZyZXkgSk9VTUFBIgpkYXRlOiAiYHIgaW52aXNpYmxlKFN5cy5zZXRsb2NhbGUobG9jYWxlID0gJ0MnKSk7IGZvcm1hdChTeXMuRGF0ZSgpLCBmb3JtYXQgPSAnJUIgJWQsICVZJylgIgpvdXRwdXQ6CiAgYm9va2Rvd246Omh0bWxfZG9jdW1lbnQyOgogICAgY3NzOiBjb3Ntb19jdXN0b20uY3NzCiAgICBudW1iZXJfc2VjdGlvbnM6IHllcwogICAgY29kZV9mb2xkaW5nOiBzaG93CiAgICBkZl9wcmludDogZGVmYXVsdAogICAgZmlnX2NhcHRpb246IHllcwogICAgY29kZV9kb3dubG9hZDogeWVzCiAgICB0b2M6IHllcwogICAgdG9jX2Zsb2F0OgogICAgICBjb2xsYXBzZWQ6IHllcwogICAgICBzbW9vdGhfc2Nyb2xsOiBubwp2aWduZXR0ZTogPgogICVcVmlnbmV0dGVJbmRleEVudHJ5e0RhdGEgRXhwbG9yYXRpb24gLSAyMDE4fQogICVcVmlnbmV0dGVFbmdpbmV7a25pdHI6OnJtYXJrZG93bn0KICAlXFZpZ25ldHRlRW5jb2Rpbmd7VVRGLTh9Ci0tLQogIApgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0KIyBjb21tYW5kIHRvIGJ1aWxkIHBhY2thZ2Ugd2l0aG91dCBnZXR0aW5nIHZpZ25ldHRlIGVycm9yCiMgaHR0cHM6Ly9naXRodWIuY29tL3JzdHVkaW8vcmVudi9pc3N1ZXMvODMzCiMgZGV2dG9vbHM6OmNoZWNrKGJ1aWxkX2FyZ3M9YygiLS1uby1idWlsZC12aWduZXR0ZXMiKSkKCiMgcmVkdWNlIHBuZyBzaXplCmtuaXRyOjprbml0X2hvb2tzJHNldChvcHRpcG5nID0ga25pdHI6Omhvb2tfb3B0aXBuZykKa25pdHI6OmtuaXRfaG9va3Mkc2V0KHBuZ3F1YW50ID0ga25pdHI6Omhvb2tfcG5ncXVhbnQpCgojIGdsb2JhbCBvcHRpb24gcmVsYXRpdmUgdG8gcm1hcmtkb3duCmtuaXRyOjpvcHRzX2NodW5rJHNldCgKICBlY2hvID0gVFJVRSwKICBmaWcuYWxpZ24gPSAiY2VudGVyIiwKICBvdXQud2lkdGggPSAiMTAwJSIsCiAgbWVzc2FnZSA9IEZBTFNFLAogIHdhcm5pbmcgPSBGQUxTRSwKICAjIHRpZHkgPSBUUlVFLAogIGNhY2hlLmxhenkgPSBGQUxTRSwKICBvcHRpcG5nID0gIi1vNyAtcXVpZXQiLAogIHBuZ3F1YW50ID0gIi0tc3BlZWQ9MSIKKQoKIyBsaWJyYXJ5CmxpYnJhcnkoZGF0YS50YWJsZSkKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KGthYmxlRXh0cmEpCmxpYnJhcnkobGVhZmxldCkKbGlicmFyeShndHN1bW1hcnkpICMgaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL2d0c3VtbWFyeS92aWduZXR0ZXMvdGJsX3N1bW1hcnkuaHRtbApsaWJyYXJ5KGNvcnJwbG90KQpsaWJyYXJ5KGdnY29ycnBsb3QpCmxpYnJhcnkoZ2duZXdzY2FsZSkKbGlicmFyeShtYWdyaXR0cikKbGlicmFyeShEVCkKbGlicmFyeShwbG90bHkpCmxpYnJhcnkoZ2Vvc3BoZXJlKQpsaWJyYXJ5KHRpZHluYykKbGlicmFyeShnZ2FuaW1hdGUpCmxpYnJhcnkodHJhbnNmb3JtcikKbGlicmFyeShtYWdpY2spCmxpYnJhcnkoZ2lmc2tpKQoKIyByZW1vdmUgc29tZSB3YXJuaW5ncwpzdXBwcmVzc1dhcm5pbmdzKGxpYnJhcnkoZ2dwbG90MikpCgojIGRlZmluZSBteSBvd24gdGFibGUgZm9ybWF0OiBodHRwczovL2dpdGh1Yi5jb20vaGFvemh1MjMzL2thYmxlRXh0cmEvaXNzdWVzLzM3NApzYWJsZSA8LSBmdW5jdGlvbih4LCBlc2NhcGUgPSBULCAuLi4pIHsKICBrbml0cjo6a2FibGUoeCwgZXNjYXBlID0gZXNjYXBlLCAuLi4pICU+JQogICAga2FibGVfc3R5bGluZygKICAgICAgYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiwgInJlc3BvbnNpdmUiKSwKICAgICAgZnVsbF93aWR0aCA9IEYKICAgICkKfQoKIyB0aGVtZSBnZ3Bsb3QKIyBiYXNlZDogaHR0cHM6Ly9iZW5qYW1pbmxvdWlzLXN0YXQuZnIvZW4vYmxvZy8yMDIwLTA1LTIxLWFzdHVjZXMtZ2dwbG90LXJtYXJrZG93bi8KdGhlbWVfampvIDwtIGZ1bmN0aW9uKGJhc2Vfc2l6ZSA9IDEyKSB7CiAgdGhlbWVfYncoYmFzZV9zaXplID0gYmFzZV9zaXplKSAlK3JlcGxhY2UlCiAgICB0aGVtZSgKICAgICAgIyB0aGUgd2hvbGUgZmlndXJlCiAgICAgICMgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gcmVsKDEpLCBmYWNlID0gImJvbGQiLCBtYXJnaW4gPSBtYXJnaW4oMCwwLDUsMCksIGhqdXN0ID0gMCksCiAgICAgICMgZmlndXJlIGFyZWEKICAgICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgcGFuZWwuYm9yZGVyID0gZWxlbWVudF9ibGFuaygpLAogICAgICAjIGF4ZXMKICAgICAgIyBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSByZWwoMC44NSksIGZhY2UgPSAiYm9sZCIpLAogICAgICAjIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gcmVsKDAuNzApLCBmYWNlID0gImJvbGQiKSwKICAgICAgYXhpcy5saW5lID0gZWxlbWVudF9saW5lKGNvbG9yID0gImJsYWNrIiwgYXJyb3cgPSBhcnJvdyhsZW5ndGggPSB1bml0KDAuMiwgImxpbmVzIiksIHR5cGUgPSAiY2xvc2VkIikpLAogICAgICAjIGxlZ2VuZAogICAgICAjIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gcmVsKDAuODUpLCBmYWNlID0gImJvbGQiKSwKICAgICAgIyBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gcmVsKDAuNzApLCBmYWNlID0gImJvbGQiKSwKICAgICAgIyBsZWdlbmQua2V5ID0gZWxlbWVudF9yZWN0KGZpbGwgPSAidHJhbnNwYXJlbnQiLCBjb2xvdXIgPSBOQSksCiAgICAgICMgbGVnZW5kLmtleS5zaXplID0gdW5pdCgxLjUsICJsaW5lcyIpLAogICAgICAjIGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAidHJhbnNwYXJlbnQiLCBjb2xvdXIgPSBOQSksCiAgICAgICMgTGVzIDxVKzAwRTk+dGlxdWV0dGVzIGRhbnMgbGUgY2FzIGQndW4gZmFjZXR0aW5nCiAgICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICIjODg4ODg4IiwgY29sb3IgPSAiIzg4ODg4OCIpLAogICAgICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSByZWwoMC44NSksIGZhY2UgPSAiYm9sZCIsIGNvbG9yID0gIndoaXRlIiwgbWFyZ2luID0gbWFyZ2luKDUsIDAsIDUsIDApKQogICAgKQp9CmBgYAoKVGhpcyBkb2N1bWVudCBhaW1zIGF0IGV4cGxvcmluZyB0aGUgZGF0YXNldCBvZiA0IGluZGl2aWR1YWxzIGluIDIwMTguIEZvciB0aGF0IHB1cnBvc2UsIHdlIG5lZWQgZmlyc3QgdG8gbG9hZCB0aGUgYHdlYW5saW5nTkVTYCBwYWNrYWdlIHRvIGxvYWQgZGF0YS4KCmBgYHtyIGRhdGEtZXhwbG9yYXRpb24tMjAxOC0xfQojIGxvYWQgbGlicmFyeQpsaWJyYXJ5KHdlYW5saW5nTkVTKQoKIyBsb2FkIGRhdGEKZGF0YSgiZGF0YV9uZXMiLCBwYWNrYWdlID0gIndlYW5saW5nTkVTIikKIyBsb2FkKCIuLi9kYXRhL2RhdGFfbmVzLnJkYSIpCmBgYAoKTGV04oCZcyBoYXZlIGEgbG9vayBhdCB3aGF04oCZcyBpbnNpZGUgYGRhdGFfbmVzJGRhdGFfMjAxOGA6CiAgCmBgYHtyIGRhdGEtZXhwbG9yYXRpb24tMjAxOC0yfQojIGxpc3Qgc3RydWN0dXJlCnN0cihkYXRhX25lcyR5ZWFyXzIwMTgsIG1heC5sZXZlbCA9IDEsIGdpdmUuYXR0ciA9IEYsIG5vLmxpc3QgPSBUKQpgYGAKCj4gQSBsaXN0IG9mIGByIGxlbmd0aChkYXRhX25lcyR5ZWFyXzIwMTgpYCBgZGF0YS5mcmFtZXNgLCBvbmUgZm9yIGVhY2ggc2VhbAoKRm9yIGNvbnZlbmllbmNlLCB3ZSBhZ2dyZWdhdGUgYWxsIGByIGxlbmd0aChkYXRhX25lcyR5ZWFyXzIwMTgpYCBpbmRpdmlkdWFscyBpbnRvIG9uZSBkYXRhc2V0LgoKYGBge3IgZGF0YS1leHBsb3JhdGlvbi0yMDE4LTMsIGV2YWw9RkFMU0V9CiMgY29tYmluZSBhbGwgaW5kaXZpZHVhbHMKZGF0YV8yMDE4IDwtIHJiaW5kbGlzdChkYXRhX25lcyR5ZWFyXzIwMTgpCgojIGRpc3BsYXkKRFQ6OmRhdGF0YWJsZShkYXRhXzIwMThbc2FtcGxlLmludCguTiwgMTApLCBdLCBvcHRpb25zID0gbGlzdChzY3JvbGxYID0gVCkpCmBgYApgYGB7ciBkYXRhLWV4cGxvcmF0aW9uLTIwMTgtNCwgZWNobz1GQUxTRSwgcmVzdWx0cz0nYXNpcyd9CiMgY29tYmluZSBhbGwgaW5kaXZpZHVhbHMKZGF0YV8yMDE4IDwtIHJiaW5kbGlzdChkYXRhX25lcyR5ZWFyXzIwMTgpCgojIHRpdGxlCmNhdCgiPHRhYmxlIHN0eWxlPSd3aWR0aDogNTAlJz4iLCAKICAgIHBhc3RlMCgKICAgICAgIjxjYXB0aW9uPiIsIAogICAgICAiKCN0YWI6bXlEVGh0bWx0b29scykiLCAKICAgICAgIlNhbXBsZSBvZiAxMCByYW5kb20gcm93cyBmcm9tIGBkYXRhXzIwMThgIiwgCiAgICAgICI8L2NhcHRpb24+IiksIAogICAgIjwvdGFibGU+IiwgCiAgICBzZXAgPSAiXG4iKQoKIyBkaXNwbGF5CkRUOjpkYXRhdGFibGUoZGF0YV8yMDE4W3NhbXBsZS5pbnQoLk4sIDEwKSwgXSwgb3B0aW9ucyA9IGxpc3Qoc2Nyb2xsWCA9IFQpKQpgYGAKCiMjIFN1bW1hcnkKCmBgYHtyIGRhdGEtZXhwbG9yYXRpb24tMjAxOC01fQojIHJhd19kYXRhCmRhdGFfMjAxOFssIC4oCiAgbmJfZGF5c19yZWNvcmRlZCA9IHVuaXF1ZU4oYXMuRGF0ZShkYXRlKSksCiAgbmJfZGl2ZXMgPSAuTiwKICBtYXhkZXB0aF9tZWFuID0gbWVhbihtYXhkZXB0aCksCiAgZGR1cmF0aW9uX21lYW4gPSBtZWFuKGRkdXJhdGlvbiksCiAgYm90dHRpbWVfbWVhbiA9IG1lYW4oYm90dHRpbWUpLAogIHBkaV9tZWFuID0gbWVhbihwZGksIG5hLnJtID0gVCkKKSwgYnkgPSAuaWRdICU+JQogIHNhYmxlKAogICAgY2FwdGlvbiA9ICJTdW1tYXJ5IGRpdmluZyBpbmZvcm1hdGlvbiByZWxhdGl2ZSB0byBlYWNoIDIwMTggaW5kaXZpZHVhbCIsCiAgICBkaWdpdHMgPSAyCiAgKQpgYGAKPiBWZXJ5IG5pY2UgZGF0YXNldCA6KQoKIyMgU29tZSBleHBsYW5hdG9yeSBwbG90cwoKIyMjIE1pc3NpbmcgdmFsdWVzCgpgYGB7ciBkYXRhLWV4cGxvcmF0aW9uLTIwMTgtNiwgZmlnLmNhcD0iQ2hlY2sgZm9yIG1pc3NpbmcgdmFsdWUgaW4gMjAxOC1pbmRpdmlkdWFscyIsIGZpZy53aWR0aD05fQojIGJ1aWxkIGRhdGFzZXQgdG8gY2hlY2sgZm9yIG1pc3NpbmcgdmFsdWVzCmRhdGFQbG90IDwtIG1lbHQoZGF0YV8yMDE4WywgLiguaWQsIGlzLm5hKC5TRCkpLCAuU0Rjb2wgPSAtYygKICAiLmlkIiwKICAiZGl2ZW51bWJlciIsCiAgInllYXIiLAogICJtb250aCIsCiAgImRheSIsCiAgImhvdXIiLAogICJtaW4iLAogICJzZWMiLAogICJqdWxkYXRlIiwKICAiZGl2ZXR5cGUiLAogICJkYXRlIiwKICAicGhhc2UiLAogICJsYXQiLAogICJsb24iCildKQojIGFkZCB0aGUgaWQgb2Ygcm93cwpkYXRhUGxvdFssIGlkX3JvdyA6PSBjKDE6Lk4pLCBieSA9IGMoInZhcmlhYmxlIiwgIi5pZCIpXQoKIyBwbG90CmdncGxvdChkYXRhUGxvdCwgYWVzKHggPSB2YXJpYWJsZSwgeSA9IGlkX3JvdywgZmlsbCA9IHZhbHVlKSkgKwogIGdlb21fdGlsZSgpICsKICBsYWJzKHggPSAiQXR0cmlidXRlcyIsIHkgPSAiUm93cyIpICsKICBzY2FsZV9maWxsX21hbnVhbCgKICAgIHZhbHVlcyA9IGMoIndoaXRlIiwgImJsYWNrIiksCiAgICBsYWJlbHMgPSBjKCJSZWFsIiwgIk1pc3NpbmciKQogICkgKwogIGZhY2V0X3dyYXAoLmlkIH4gLiwgc2NhbGVzID0gImZyZWVfeSIpICsKICB0aGVtZV9qam8oKSArCiAgdGhlbWUoCiAgICBsZWdlbmQucG9zaXRpb24gPSAidG9wIiwKICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSksCiAgICBsZWdlbmQua2V5ID0gZWxlbWVudF9yZWN0KGNvbG91ciA9ICJibGFjayIpCiAgKQpgYGAKClNvIGZhciBzbyBnb29kLCBvbmx5IGZldyB2YXJpYWJsZXMgc2VlbXMgdG8gaGF2ZSBtaXNzaW5nIHZhbHVlczoKICAKYGBge3IgZGF0YS1leHBsb3JhdGlvbi0yMDE4LTd9CiMgdGFibGUgd2l0aCBwZXJjZW50CnRhYmxlX2ludGVyIDwtIGRhdGFfMjAxOFssIGxhcHBseSguU0QsIGZ1bmN0aW9uKHgpIHsKICByb3VuZChsZW5ndGgoeFtpcy5uYSh4KV0pICogMTAwIC8gbGVuZ3RoKHgpLCAxKQp9KSwgLlNEY29sID0gLWMoCiAgIi5pZCIsCiAgImRpdmVudW1iZXIiLAogICJ5ZWFyIiwKICAibW9udGgiLAogICJkYXkiLAogICJob3VyIiwKICAibWluIiwKICAic2VjIiwKICAianVsZGF0ZSIsCiAgImRpdmV0eXBlIiwKICAiZGF0ZSIsCiAgInBoYXNlIiwKICAibGF0IiwKICAibG9uIgopXQoKIyBmaW5kIHdoaWNoIGFyZSBkaWZmZXJlbnQgZnJvbSAwCmNvbmRfaW50ZXIgPC0gc2FwcGx5KHRhYmxlX2ludGVyLCBmdW5jdGlvbih4KSB7CiAgeCA9PSAwCn0pCgojIGRpc3BsYXkgdGhlIHBlcmNlbnRhZ2VzIHRoYXQgYXJlIG92ZXIgMAp0YWJsZV9pbnRlclssIHdoaWNoKGNvbmRfaW50ZXIpIDo9IE5VTExdICU+JQogIHNhYmxlKGNhcHRpb24gPSAiUGVyY2VudGFnZSBvZiBtaXNzaW5nIHZhbHVlcyBwZXIgY29sdW1ucyBoYXZpbmcgbWlzc2luZyB2YWx1ZXMhIikgJT4lCiAgc2Nyb2xsX2JveCh3aWR0aCA9ICIxMDAlIikKYGBgCgojIyMgT3V0bGllcnMgey50YWJzZXR9CgpPaywgbGV0J3MgaGF2ZSBhIGxvb2sgYXQgYWxsIHRoZSBkYXRhLiBCdXQgZmlyc3QsIHdlIGhhdmUgdG8gcmVtb3ZlIG91dGxpZXJzLiBTb21lIG9mIHRoZW0gYXJlIHF1aWV0IGVhc3kgdG8gc3BvdCBsb29raW5nIGF0IHRoZSBkaXN0cmlidXRpb24gb2YgZGl2ZSBkdXJhdGlvbjoKCiMjIyMgQmVmb3JlIHstfQoKYGBge3IgZGF0YS1leHBsb3JhdGlvbi0yMDE4LTgsIGZpZy5jYXA9J0Rpc3RyaWJ1dGlvbiBvZiBgZGR1cmF0aW9uYCBmb3IgZWFjaCBzZWFsLiBUaGUgZGFzaGVkIGxpbmUgaGlnaGxpZ2h0IHRoZSAic3ViamVjdGl2ZSIgdGhyZXNob2xkIHVzZWQgdG8gcmVtb3ZlIG91dGxpZXJzICgzMDAwIHNlYyknLCBmaWcuaGVpZ2h0PTN9CmdncGxvdCgKICBkYXRhXzIwMThbLCAuU0RdWywgc3RhdGUgOj0gIkJlZm9yZSJdLAogIGFlcyh4ID0gZGR1cmF0aW9uLCBmaWxsID0gLmlkKQopICsKICBnZW9tX2hpc3RvZ3JhbShzaG93LmxlZ2VuZCA9IEZBTFNFKSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMzAwMCwgbGluZXR5cGUgPSAibG9uZ2Rhc2giKSArCiAgZmFjZXRfZ3JpZChzdGF0ZSB+IC5pZCwKICAgICAgICAgICAgIHNjYWxlcyA9ICJmcmVlIgogICkgKwogIGxhYnMoeSA9ICIjIG9mIGRpdmVzIiwgeCA9ICJEaXZlIGR1cmF0aW9uIChzKSIpICsKICB0aGVtZV9qam8oKQpgYGAKCiMjIyMgQWZ0ZXIgey19CgpgYGB7ciBkYXRhLWV4cGxvcmF0aW9uLTIwMTgtOSwgZmlnLmNhcD0nU2FtZSBkaXN0cmlidXRpb24gb2YgYGRkdXJhdGlvbmAgZm9yIGVhY2ggc2VhbCBidXQgYWZ0ZXIgcmVtb3ZpbmcgYW55IGBkZHVyYXRpb25gID4gMzAwMCBzZWMuIFRoZSBkYXNoZWQgbGluZSBoaWdobGlnaHQgdGhlICJzdWJqZWN0aXZlIiB0aHJlc2hvbGQgdXNlZCB0byByZW1vdmUgb3V0bGllcnMnLCBmaWcuaGVpZ2h0PTN9CmdncGxvdCgKICBkYXRhXzIwMThbZGR1cmF0aW9uIDwgMzAwMCwgXVtdWywgc3RhdGUgOj0gIkFmdGVyIl0sCiAgYWVzKHggPSBkZHVyYXRpb24sIGZpbGwgPSAuaWQpCikgKwogIGdlb21faGlzdG9ncmFtKHNob3cubGVnZW5kID0gRkFMU0UpICsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAzMDAwLCBsaW5ldHlwZSA9ICJsb25nZGFzaCIpICsKICBmYWNldF9ncmlkKHN0YXRlIH4gLmlkLAogICAgICAgICAgICAgc2NhbGVzID0gImZyZWUiCiAgKSArCiAgbGFicyh4ID0gIiMgb2YgZGl2ZXMiLCB5ID0gIkRpdmUgZHVyYXRpb24gKHMpIikgKwogIHRoZW1lX2pqbygpCmBgYAoKSXQgc2VlbXMgbXVjaCBiZXR0ZXIsIHNvIGxldCdzIHJlbW92ZSBhbnkgcm93cyB3aXRoIGBkZHVyYXRpb25gID4gMzAwMCBzZWMuCgpgYGB7ciBkYXRhLWV4cGxvcmF0aW9uLTIwMTgtMTB9CiMgZmlsdGVyIGRhdGEKZGF0YV8yMDE4X2ZpbHRlciA8LSBkYXRhXzIwMThbZGR1cmF0aW9uIDwgMzAwMCwgXQoKIyBuYnJvdyByZW1vdmVkCmRhdGFfMjAxOFtkZHVyYXRpb24gPj0gMzAwMCwgLihuYl9yb3dfcmVtb3ZlZCA9IC5OKSwgYnkgPSAuaWRdICU+JQogIHNhYmxlKGNhcHRpb24gPSAiIyBvZiByb3dzIHJlbW92ZWQgYnkgMjAxOC1pbmRpdmlkdWFscyIpCmBgYAoKIyMjIENoZWNrIGRheSBhbmQgbmlnaHQgey50YWJzZXR9CgojIyMjIExpZ2h0IGxldmVscwoKYGBge3IgZGF0YS1leHBsb3JhdGlvbi0yMDE4LTExLCBmaWcuY2FwPSJWaXN1YWxpemF0aW9uIG9mIGxpZ2h0IGxldmVsIGF0IHRoZSBzdXJmYWNlIGFsb25nIDIwMTgtaW5kaXZpZHVhbHMnIHRyaXAiLCBmaWcuaGVpZ2h0PTZ9CiMgbGV0J3MgZmlyc3QgYXZlcmFnZSBgbGlnaHRhdHN1cmZgIGJ5IGluZGl2aWR1YWxzLCBkYXkgc2luY2UgZGVwYXJ0dXJlIGFuZCBob3VyCmRhdGFQbG90IDwtIGRhdGFfMjAxOFssIC4obGlnaHRhdHN1cmYgPSBtZWRpYW4obGlnaHRhdHN1cmYpKSwKICAgICAgICAgICAgICAgICAgICAgIGJ5ID0gLiguaWQsIGRheV9kZXBhcnR1cmUsIGRhdGUgPSBhcy5EYXRlKGRhdGUpLCBob3VyKQpdCgojIGRpc3BsYXkgdGhlIHJlc3VsdApnZ3Bsb3QoZGF0YVBsb3QsIGFlcyh4ID0gZGF5X2RlcGFydHVyZSwgeSA9IGhvdXIsIGZpbGwgPSBsaWdodGF0c3VyZikpICsKICBnZW9tX3RpbGUoKSArCiAgZmFjZXRfZ3JpZCguaWQgfiAuKSArCiAgdGhlbWVfampvKCkgKwogIGxhYnMoeCA9ICIjIG9mIGRheXMgc2luY2UgZGVwYXJ0dXJlIiwgCiAgICAgICB5ID0gIkhvdXIiLCAKICAgICAgIGZpbGwgPSAiTGlnaHQgbGV2ZWwgYXQgdGhlIHN1cmZhY2UiKSsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSBjKCJib3R0b20iKSkKYGBgCgojIyMjIERheSBhbmQgbmlnaHQgZGV0ZWN0aW9uCgpgYGB7ciBkYXRhLWV4cGxvcmF0aW9uLTIwMTgtMTIsIGZpZy5jYXA9IlZpc3VhbGl6YXRpb24gb2YgZGV0ZWN0ZWQgbmlnaHQgdGltZSBhbmQgZGF5IHRpbWUgYWxvbmcgMjAxOC1pbmRpdmlkdWFscycgdHJpcCIsIGZpZy5oZWlnaHQ9Nn0KIyBsZXQncyBmaXJzdCBhdmVyYWdlIGBsaWdodGF0c3VyZmAgYnkgaW5kaXZpZHVhbHMsIGRheSBzaW5jZSBkZXBhcnR1cmUgYW5kIGhvdXIKZGF0YVBsb3QgPC0gZGF0YV8yMDE4WywgLihsaWdodGF0c3VyZiA9IG1lZGlhbihsaWdodGF0c3VyZikpLAogICAgICAgICAgICAgICAgICAgICAgYnkgPSAuKC5pZCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF5X2RlcGFydHVyZSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0ZSA9IGFzLkRhdGUoZGF0ZSksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhvdXIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBoYXNlKQpdCgojIGRpc3BsYXkgdGhlIHJlc3VsdApnZ3Bsb3QoZGF0YVBsb3QsIGFlcyh4ID0gZGF5X2RlcGFydHVyZSwgeSA9IGhvdXIsIGZpbGwgPSBwaGFzZSkpICsKICBnZW9tX3RpbGUoKSArCiAgZmFjZXRfZ3JpZCguaWQgfiAuKSArCiAgdGhlbWVfampvKCkgKwogIGxhYnMoeCA9ICIjIG9mIGRheXMgc2luY2UgZGVwYXJ0dXJlIiwgCiAgICAgICB5ID0gIkhvdXIiLCAKICAgICAgIGZpbGwgPSAiRGF5IHRpbWUgYW5kIG5pZ2h0IHRpbWUgYXMgZGV0ZWN0ZWQgYnkgdGhlIGBjYWxfcGhhc2VfZGF5YCBmdW5jdGlvbiIpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSBjKCJib3R0b20iKSkKYGBgCgojIyMgQWxsIFZhcmlhYmxlcyAKCmBgYHtyIGRhdGEtZXhwbG9yYXRpb24tMjAxOC0xM30KbmFtZXNfZGlzcGxheSA8LSBuYW1lcyhkYXRhXzIwMThfZmlsdGVyWywgLWMoCiAgIi5pZCIsCiAgImRhdGUiLAogICJkaXZlbnVtYmVyIiwKICAieWVhciIsCiAgIm1vbnRoIiwKICAiZGF5IiwKICAiaG91ciIsCiAgIm1pbiIsCiAgInNlYyIsCiAgImp1bGRhdGUiLAogICJkaXZldHlwZSIsCiAgImV1cGhvdGljZGVwdGgiLAogICJ0aGVybW9jbGluZWRlcHRoIiwKICAiZGF5X2RlcGFydHVyZSIsCiAgInBoYXNlIiwKICAibGF0IiwKICAibG9uIiwKICAiZGlzdF9kZXAiCildKQpgYGAKCmBgYHtyIGRhdGEtZXhwbG9yYXRpb24tMjAxOC0xNCwgZXZhbD1GQUxTRSwgaW5jbHVkZT1UUlVFfQpmb3IgKGkgaW4gbmFtZXNfZGlzcGxheSkgewogIGNhdCgiIyMjIyMiLCBpLCAiey51bmxpc3RlZCAudW5udW1iZXJlZH0gXG4iKQogIGlmIChpID09ICJtYXhkZXB0aCIpIHsKICAgIHByaW50KAogICAgICBnZ3Bsb3QoKSArCiAgICAgICAgZ2VvbV9wb2ludCgKICAgICAgICAgIGRhdGEgPSBkYXRhXzIwMThfZmlsdGVyWywgLigKICAgICAgICAgICAgLmlkLAogICAgICAgICAgICBkYXRlLAogICAgICAgICAgICB0aGVybW9jbGluZWRlcHRoCiAgICAgICAgICApXSwKICAgICAgICAgIGFlcygKICAgICAgICAgICAgeCA9IGFzLkRhdGUoZGF0ZSksCiAgICAgICAgICAgIHkgPSAtdGhlcm1vY2xpbmVkZXB0aCwKICAgICAgICAgICAgY29sb3VyID0gIlRoZXJtb2NsaW5lIChtKSIKICAgICAgICAgICksCiAgICAgICAgICBhbHBoYSA9IC4yLAogICAgICAgICAgc2l6ZSA9IC41CiAgICAgICAgKSArCiAgICAgICAgZ2VvbV9wb2ludCgKICAgICAgICAgIGRhdGEgPSBkYXRhXzIwMThfZmlsdGVyWywgLigKICAgICAgICAgICAgLmlkLAogICAgICAgICAgICBkYXRlLAogICAgICAgICAgICBldXBob3RpY2RlcHRoCiAgICAgICAgICApXSwKICAgICAgICAgIGFlcygKICAgICAgICAgICAgeCA9IGFzLkRhdGUoZGF0ZSksCiAgICAgICAgICAgIHkgPSAtZXVwaG90aWNkZXB0aCwKICAgICAgICAgICAgY29sb3VyID0gIkV1cGhvdGljIChtKSIKICAgICAgICAgICksCiAgICAgICAgICBhbHBoYSA9IC4yLAogICAgICAgICAgc2l6ZSA9IC41CiAgICAgICAgKSArCiAgICAgICAgc2NhbGVfY29sb3VyX21hbnVhbCgKICAgICAgICAgIHZhbHVlcyA9IGMoCiAgICAgICAgICAgICJUaGVybW9jbGluZSAobSkiID0gInJlZCIsCiAgICAgICAgICAgICJFdXBob3RpYyAobSkiID0gImJsYWNrIgogICAgICAgICAgKSwKICAgICAgICAgIG5hbWUgPSAiWm9uZSIKICAgICAgICApICsKICAgICAgICBuZXdfc2NhbGVfY29sb3IoKSArCiAgICAgICAgZ2VvbV9wb2ludCgKICAgICAgICAgIGRhdGEgPSBtZWx0KGRhdGFfMjAxOF9maWx0ZXJbLCAuKC5pZCwgZGF0ZSwgZ2V0KGkpKV0sIAogICAgICAgICAgICAgICAgICAgICAgaWQudmFycyA9IGMoIi5pZCIsICJkYXRlIikpLAogICAgICAgICAgYWVzKAogICAgICAgICAgICB4ID0gYXMuRGF0ZShkYXRlKSwKICAgICAgICAgICAgeSA9IC12YWx1ZSwKICAgICAgICAgICAgY29sID0gLmlkCiAgICAgICAgICApLAogICAgICAgICAgYWxwaGEgPSAxIC8gMTAsCiAgICAgICAgICBzaXplID0gLjUsCiAgICAgICAgICBzaG93LmxlZ2VuZCA9IEZBTFNFCiAgICAgICAgKSArCiAgICAgICAgZmFjZXRfd3JhcCguIH4gLmlkLCBzY2FsZXMgPSAiZnJlZSIpICsKICAgICAgICBzY2FsZV94X2RhdGUoZGF0ZV9sYWJlbHMgPSAiJW0vJVkiKSArCiAgICAgICAgbGFicyh4ID0gIkRhdGUiLCB5ID0gIk1heGltdW0gRGVwdGggKG0pIikgKwogICAgICAgIHRoZW1lX2pqbygpICsKICAgICAgICB0aGVtZSgKICAgICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSksCiAgICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIgogICAgICAgICkKICAgICkKICAgIGNhdCgiPGJsb2NrcXVvdGU+IENvbnNpZGVyaW5nIGBpbmRfMjAxODA3NGAgaGFzIHNsaWdodGx5IGRpZmZlcmVudCB2YWx1ZXMgdGhhbiBvdGhlciBpbmRpdmlkdWFscyBmb3IgdGhlIHRoZXJtb2NsaW5lIGRlcHRoLCBpdCB3b3VsZCBiZSBpbnRlcmVzdGluZyB0byBzZWUgd2hlcmUgdGhlIGFuaW1hbCB3ZW50LiA8L2Jsb2NrcXVvdGU+IikKICB9IGVsc2UgaWYgKGkgPT0gImRyaWZ0cmF0ZSIpIHsKICAgIHByaW50KAogICAgICBnZ3Bsb3QoCiAgICAgICAgZGF0YSA9IG1lbHQoZGF0YV8yMDE4X2ZpbHRlclssIC4oLmlkLCBkYXRlLCBnZXQoaSksIGRpdmV0eXBlKV0sIAogICAgICAgICAgICAgICAgICAgIGlkLnZhcnMgPSBjKCIuaWQiLCAiZGF0ZSIsICJkaXZldHlwZSIpKSwKICAgICAgICBhZXMoCiAgICAgICAgICB4ID0gYXMuRGF0ZShkYXRlKSwKICAgICAgICAgIHkgPSB2YWx1ZSwKICAgICAgICAgIGNvbCA9IGRpdmV0eXBlCiAgICAgICAgKQogICAgICApICsKICAgICAgICBnZW9tX3BvaW50KAogICAgICAgICAgYWxwaGEgPSAxIC8gMTAsCiAgICAgICAgICBzaXplID0gLjUKICAgICAgICApICsKICAgICAgICBmYWNldF93cmFwKC4gfiAuaWQsIHNjYWxlcyA9ICJmcmVlIikgKwogICAgICAgIHNjYWxlX3hfZGF0ZShkYXRlX2xhYmVscyA9ICIlbS8lWSIpICsKICAgICAgICBsYWJzKHggPSAiRGF0ZSIsIHkgPSAiRHJpZnQgUmF0ZSAnbS9zIiwgY29sID0gIkRpdmUgVHlwZSIpICsKICAgICAgICB0aGVtZV9qam8oKSArCiAgICAgICAgdGhlbWUoCiAgICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpLAogICAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIKICAgICAgICApICsKICAgICAgICBndWlkZXMoY29sb3VyID0gZ3VpZGVfbGVnZW5kKG92ZXJyaWRlLmFlcyA9IGxpc3QoCiAgICAgICAgICBzaXplID0gNywKICAgICAgICAgIGFscGhhID0gMQogICAgICAgICkpKQogICAgKQogIH0gZWxzZSB7CiAgICBwcmludCgKICAgICAgZ2dwbG90KAogICAgICAgIGRhdGEgPSBtZWx0KGRhdGFfMjAxOF9maWx0ZXJbLCAuKC5pZCwgZGF0ZSwgZ2V0KGkpKV0sIAogICAgICAgICAgICAgICAgICAgIGlkLnZhcnMgPSBjKCIuaWQiLCAiZGF0ZSIpKSwKICAgICAgICBhZXMoCiAgICAgICAgICB4ID0gYXMuRGF0ZShkYXRlKSwKICAgICAgICAgIHkgPSB2YWx1ZSwKICAgICAgICAgIGNvbCA9IC5pZAogICAgICAgICkKICAgICAgKSArCiAgICAgICAgZ2VvbV9wb2ludCgKICAgICAgICAgIHNob3cubGVnZW5kID0gRkFMU0UsCiAgICAgICAgICBhbHBoYSA9IDEgLyAxMCwKICAgICAgICAgIHNpemUgPSAuNQogICAgICAgICkgKwogICAgICAgIGZhY2V0X3dyYXAoLiB+IC5pZCwgc2NhbGVzID0gImZyZWUiKSArCiAgICAgICAgc2NhbGVfeF9kYXRlKGRhdGVfbGFiZWxzID0gIiVtLyVZIikgKwogICAgICAgIGxhYnMoeCA9ICJEYXRlIiwgeSA9IGkpICsKICAgICAgICB0aGVtZV9qam8oKSArCiAgICAgICAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkKICAgICkKICB9CiAgCiAgY2F0KCJcbiBcbiIpCn0KYGBgCgojIyMgey51bmxpc3RlZCAudW5udW1iZXJlZCAudGFic2V0IC50YWJzZXQtZmFkZSAudGFic2V0LXBpbGxzfQoKYGBge3IgZGF0YS1leHBsb3JhdGlvbi0yMDE4LTE1LCByZXN1bHRzPSdhc2lzJywgY2FjaGU9VFJVRSwgZWNobz1GQUxTRX0KZm9yIChpIGluIG5hbWVzX2Rpc3BsYXkpIHsKICBjYXQoIiMjIyMiLCBpLCAiey51bmxpc3RlZCAudW5udW1iZXJlZH0gXG4iKQogIGlmIChpID09ICJtYXhkZXB0aCIpIHsKICAgIHByaW50KAogICAgICBnZ3Bsb3QoKSArCiAgICAgICAgZ2VvbV9wb2ludCgKICAgICAgICAgIGRhdGEgPSBkYXRhXzIwMThfZmlsdGVyWywgLigKICAgICAgICAgICAgLmlkLAogICAgICAgICAgICBkYXRlLAogICAgICAgICAgICB0aGVybW9jbGluZWRlcHRoCiAgICAgICAgICApXSwKICAgICAgICAgIGFlcygKICAgICAgICAgICAgeCA9IGFzLkRhdGUoZGF0ZSksCiAgICAgICAgICAgIHkgPSAtdGhlcm1vY2xpbmVkZXB0aCwKICAgICAgICAgICAgY29sb3VyID0gIlRoZXJtb2NsaW5lIChtKSIKICAgICAgICAgICksCiAgICAgICAgICBhbHBoYSA9IC4yLAogICAgICAgICAgc2l6ZSA9IC41CiAgICAgICAgKSArCiAgICAgICAgZ2VvbV9wb2ludCgKICAgICAgICAgIGRhdGEgPSBkYXRhXzIwMThfZmlsdGVyWywgLigKICAgICAgICAgICAgLmlkLAogICAgICAgICAgICBkYXRlLAogICAgICAgICAgICBldXBob3RpY2RlcHRoCiAgICAgICAgICApXSwKICAgICAgICAgIGFlcygKICAgICAgICAgICAgeCA9IGFzLkRhdGUoZGF0ZSksCiAgICAgICAgICAgIHkgPSAtZXVwaG90aWNkZXB0aCwKICAgICAgICAgICAgY29sb3VyID0gIkV1cGhvdGljIChtKSIKICAgICAgICAgICksCiAgICAgICAgICBhbHBoYSA9IC4yLAogICAgICAgICAgc2l6ZSA9IC41CiAgICAgICAgKSArCiAgICAgICAgc2NhbGVfY29sb3VyX21hbnVhbCgKICAgICAgICAgIHZhbHVlcyA9IGMoCiAgICAgICAgICAgICJUaGVybW9jbGluZSAobSkiID0gInJlZCIsCiAgICAgICAgICAgICJFdXBob3RpYyAobSkiID0gImJsYWNrIgogICAgICAgICAgKSwKICAgICAgICAgIG5hbWUgPSAiWm9uZSIKICAgICAgICApICsKICAgICAgICBuZXdfc2NhbGVfY29sb3IoKSArCiAgICAgICAgZ2VvbV9wb2ludCgKICAgICAgICAgIGRhdGEgPSBtZWx0KGRhdGFfMjAxOF9maWx0ZXJbLCAuKC5pZCwgZGF0ZSwgZ2V0KGkpKV0sIAogICAgICAgICAgICAgICAgICAgICAgaWQudmFycyA9IGMoIi5pZCIsICJkYXRlIikpLAogICAgICAgICAgYWVzKAogICAgICAgICAgICB4ID0gYXMuRGF0ZShkYXRlKSwKICAgICAgICAgICAgeSA9IC12YWx1ZSwKICAgICAgICAgICAgY29sID0gLmlkCiAgICAgICAgICApLAogICAgICAgICAgYWxwaGEgPSAxIC8gMTAsCiAgICAgICAgICBzaXplID0gLjUsCiAgICAgICAgICBzaG93LmxlZ2VuZCA9IEZBTFNFCiAgICAgICAgKSArCiAgICAgICAgZmFjZXRfd3JhcCguIH4gLmlkLCBzY2FsZXMgPSAiZnJlZSIpICsKICAgICAgICBzY2FsZV94X2RhdGUoZGF0ZV9sYWJlbHMgPSAiJW0vJVkiKSArCiAgICAgICAgbGFicyh4ID0gIkRhdGUiLCB5ID0gIk1heGltdW0gRGVwdGggKG0pIikgKwogICAgICAgIHRoZW1lX2pqbygpICsKICAgICAgICB0aGVtZSgKICAgICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSksCiAgICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIgogICAgICAgICkKICAgICkKICAgIGNhdCgiPGJsb2NrcXVvdGU+IENvbnNpZGVyaW5nIGBpbmRfMjAxODA3NGAgaGFzIHNsaWdodGx5IGRpZmZlcmVudCB2YWx1ZXMgdGhhbiBvdGhlciBpbmRpdmlkdWFscyBmb3IgdGhlIHRoZXJtb2NsaW5lIGRlcHRoLCBpdCB3b3VsZCBiZSBpbnRlcmVzdGluZyB0byBzZWUgd2hlcmUgdGhlIGFuaW1hbCB3ZW50LiA8L2Jsb2NrcXVvdGU+IikKICB9IGVsc2UgaWYgKGkgPT0gImRyaWZ0cmF0ZSIpIHsKICAgIHByaW50KAogICAgICBnZ3Bsb3QoCiAgICAgICAgZGF0YSA9IG1lbHQoZGF0YV8yMDE4X2ZpbHRlclssIC4oLmlkLCBkYXRlLCBnZXQoaSksIGRpdmV0eXBlKV0sIAogICAgICAgICAgICAgICAgICAgIGlkLnZhcnMgPSBjKCIuaWQiLCAiZGF0ZSIsICJkaXZldHlwZSIpKSwKICAgICAgICBhZXMoCiAgICAgICAgICB4ID0gYXMuRGF0ZShkYXRlKSwKICAgICAgICAgIHkgPSB2YWx1ZSwKICAgICAgICAgIGNvbCA9IGRpdmV0eXBlCiAgICAgICAgKQogICAgICApICsKICAgICAgICBnZW9tX3BvaW50KAogICAgICAgICAgYWxwaGEgPSAxIC8gMTAsCiAgICAgICAgICBzaXplID0gLjUKICAgICAgICApICsKICAgICAgICBmYWNldF93cmFwKC4gfiAuaWQsIHNjYWxlcyA9ICJmcmVlIikgKwogICAgICAgIHNjYWxlX3hfZGF0ZShkYXRlX2xhYmVscyA9ICIlbS8lWSIpICsKICAgICAgICBsYWJzKHggPSAiRGF0ZSIsIHkgPSAiRHJpZnQgUmF0ZSAnbS9zIiwgY29sID0gIkRpdmUgVHlwZSIpICsKICAgICAgICB0aGVtZV9qam8oKSArCiAgICAgICAgdGhlbWUoCiAgICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpLAogICAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIKICAgICAgICApICsKICAgICAgICBndWlkZXMoY29sb3VyID0gZ3VpZGVfbGVnZW5kKG92ZXJyaWRlLmFlcyA9IGxpc3QoCiAgICAgICAgICBzaXplID0gNywKICAgICAgICAgIGFscGhhID0gMQogICAgICAgICkpKQogICAgKQogIH0gZWxzZSB7CiAgICBwcmludCgKICAgICAgZ2dwbG90KAogICAgICAgIGRhdGEgPSBtZWx0KGRhdGFfMjAxOF9maWx0ZXJbLCAuKC5pZCwgZGF0ZSwgZ2V0KGkpKV0sIAogICAgICAgICAgICAgICAgICAgIGlkLnZhcnMgPSBjKCIuaWQiLCAiZGF0ZSIpKSwKICAgICAgICBhZXMoCiAgICAgICAgICB4ID0gYXMuRGF0ZShkYXRlKSwKICAgICAgICAgIHkgPSB2YWx1ZSwKICAgICAgICAgIGNvbCA9IC5pZAogICAgICAgICkKICAgICAgKSArCiAgICAgICAgZ2VvbV9wb2ludCgKICAgICAgICAgIHNob3cubGVnZW5kID0gRkFMU0UsCiAgICAgICAgICBhbHBoYSA9IDEgLyAxMCwKICAgICAgICAgIHNpemUgPSAuNQogICAgICAgICkgKwogICAgICAgIGZhY2V0X3dyYXAoLiB+IC5pZCwgc2NhbGVzID0gImZyZWUiKSArCiAgICAgICAgc2NhbGVfeF9kYXRlKGRhdGVfbGFiZWxzID0gIiVtLyVZIikgKwogICAgICAgIGxhYnMoeCA9ICJEYXRlIiwgeSA9IGkpICsKICAgICAgICB0aGVtZV9qam8oKSArCiAgICAgICAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkKICAgICkKICB9CiAgCiAgY2F0KCJcbiBcbiIpCn0KYGBgCgojIyMgey51bmxpc3RlZCAudW5udW1iZXJlZH0KCj4gRmV3IHF1ZXN0aW9ucywgdGhhdCBJIHNob3VsZCBsb29rIGludG8gaXQ6CiAgPgogID4gKiBpcyB0aGUgYmltb2RhbCBkaXN0cmlidXRpb24gb2YgYGRkdXJhdGlvbmAsIGBkZXNjdGltZWAgZHVlIHRvIG55Y3RoZW1lcmFsIG1pZ3JhdGlvbj8KICA+ICogaXMgdGhlIGJpbW9kYWwgZGlzdHJpYnV0aW9uIG9mIGBkZXNjcmF0ZWAgKGVzcGVjaWFsbHkgZm9yIGBpbmQyMDE4MDcwYCBhbmQgYGluZF8yMDE4MDcyYCkgZHVlIHRvIGRyaWZ0IGRpdmU/CiAgPiAqIGlzIGBsaWdodGF0Ym90dGAgY291bGQgYmUgdXNlZCB0byBpZGVudGlmeSBiaW9sdW1pbmVzY2VuY2UsIGNhdXNlIGl0IHNlZW1zIHRoZXJlIGlzIGEgbG90IGdvaW5nIG9uIGF0IHRoZSBib3R0b20/CiAgPiAqIGFyZSB0aGUgdmFyaWF0aW9ucyBvYnNlcnZlZCBmb3IgYGxpZ2h0YXRzdXJmYCBpcyBkdWUgdG8gbW9vbiBjeWNsZT8KICA+ICogbm90IHN1cmUgd2h5IGlzIHRoZXJlIGEgYmltb2RhbCBkaXN0cmlidXRpb24gb2YgYHRlbXBhdGJvdHRgIQogID4gKiBgZHJpZnJhdGVgIHRoYXQgb25lIGlzIGF3ZXNvbWUhIFRoYW5rcyB0byBgZGl2ZXR5cGVgIHdlIGNhbiBjbGVhcmx5IHNlZSBhIHBhdHRlcm4gb2YgaG93IGRyaWZ0cmF0ZSAoYW5kIHNvIGJ1b3lhbmN5KSBjaGFuZ2UgYWNjb3JkaW5nIHRpbWUuCj4gKiB0aGUgYmltb2RhbCBkaXN0cmlidXRpb24gb2YgYHZlcnRpY2Fsc3BlZWQ5MGAgYW5kIGB2ZXJ0aWNhbHNwZWVkOTVgIHNob3VsZCBiZSBkdWUgdG8gZHJpZnQgZGl2ZS4KCmBgYHtyIGRhdGEtZXhwbG9yYXRpb24tMjAxOC0xNiwgZXZhbD1GQUxTRSwgaW5jbHVkZT1UUlVFfQojIHNhbWUgcGxvdCB3aXRoIGEgY29sb3JlZCBmb3IgdGhlIHBoYXNlIG9mIHRoZSBkYXkKZm9yIChpIGluIG5hbWVzX2Rpc3BsYXkpIHsKICBjYXQoIiMjIyMiLCBpLCAiey19IFxuIikKICBwcmludCgKICAgIGdncGxvdCgKICAgICAgZGF0YSA9IG1lbHQoZGF0YV8yMDE4X2ZpbHRlclssIC4oLmlkLCBkYXRlLCBnZXQoaSksIHBoYXNlKV0sCiAgICAgICAgICAgICAgICAgIGlkLnZhcnMgPSBjKAogICAgICAgICAgICAgICAgICAgICIuaWQiLAogICAgICAgICAgICAgICAgICAgICJkYXRlIiwKICAgICAgICAgICAgICAgICAgICAicGhhc2UiCiAgICAgICAgICAgICAgICAgICkKICAgICAgKSwKICAgICAgYWVzKAogICAgICAgIHggPSBhcy5EYXRlKGRhdGUpLAogICAgICAgIHkgPSB2YWx1ZSwKICAgICAgICBjb2wgPSBwaGFzZQogICAgICApCiAgICApICsKICAgICAgZ2VvbV9wb2ludCgKICAgICAgICBhbHBoYSA9IDEgLyAxMCwKICAgICAgICBzaXplID0gLjUKICAgICAgKSArCiAgICAgIGZhY2V0X3dyYXAoLiB+IC5pZCwgc2NhbGVzID0gImZyZWUiKSArCiAgICAgIHNjYWxlX3hfZGF0ZShkYXRlX2xhYmVscyA9ICIlbS8lWSIpICsKICAgICAgbGFicyh4ID0gIkRhdGUiLCB5ID0gaSkgKwogICAgICB0aGVtZV9qam8oKSArCiAgICAgIHRoZW1lKAogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSksCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIKICAgICAgKSArCiAgICAgIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9sZWdlbmQob3ZlcnJpZGUuYWVzID0gbGlzdCgKICAgICAgICBzaXplID0gNywKICAgICAgICBhbHBoYSA9IDEKICAgICAgKSkpCiAgKQogIGNhdCgiXG4gXG4iKQp9CmBgYAoKIyMjIHsudW5saXN0ZWQgLnVubnVtYmVyZWQgLnRhYnNldCAudGFic2V0LWZhZGUgLnRhYnNldC1waWxsc30KCmBgYHtyIGRhdGEtZXhwbG9yYXRpb24tMjAxOC0xNywgcmVzdWx0cz0nYXNpcycsIGNhY2hlPVRSVUUsIGVjaG89RkFMU0V9CiMgc2FtZSBwbG90IHdpdGggYSBjb2xvcmVkIGZvciB0aGUgcGhhc2Ugb2YgdGhlIGRheQpmb3IgKGkgaW4gbmFtZXNfZGlzcGxheSkgewogIGNhdCgiIyMjIyIsIGksICJ7LX0gXG4iKQogIHByaW50KAogICAgZ2dwbG90KAogICAgICBkYXRhID0gbWVsdChkYXRhXzIwMThfZmlsdGVyWywgLiguaWQsIGRhdGUsIGdldChpKSwgcGhhc2UpXSwKICAgICAgICAgICAgICAgICAgaWQudmFycyA9IGMoCiAgICAgICAgICAgICAgICAgICAgIi5pZCIsCiAgICAgICAgICAgICAgICAgICAgImRhdGUiLAogICAgICAgICAgICAgICAgICAgICJwaGFzZSIKICAgICAgICAgICAgICAgICAgKQogICAgICApLAogICAgICBhZXMoCiAgICAgICAgeCA9IGFzLkRhdGUoZGF0ZSksCiAgICAgICAgeSA9IHZhbHVlLAogICAgICAgIGNvbCA9IHBoYXNlCiAgICAgICkKICAgICkgKwogICAgICBnZW9tX3BvaW50KAogICAgICAgIGFscGhhID0gMSAvIDEwLAogICAgICAgIHNpemUgPSAuNQogICAgICApICsKICAgICAgZmFjZXRfd3JhcCguIH4gLmlkLCBzY2FsZXMgPSAiZnJlZSIpICsKICAgICAgc2NhbGVfeF9kYXRlKGRhdGVfbGFiZWxzID0gIiVtLyVZIikgKwogICAgICBsYWJzKHggPSAiRGF0ZSIsIHkgPSBpKSArCiAgICAgIHRoZW1lX2pqbygpICsKICAgICAgdGhlbWUoCiAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSwKICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIgogICAgICApICsKICAgICAgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2xlZ2VuZChvdmVycmlkZS5hZXMgPSBsaXN0KAogICAgICAgIHNpemUgPSA3LAogICAgICAgIGFscGhhID0gMQogICAgICApKSkKICApCiAgY2F0KCJcbiBcbiIpCn0KYGBgCgojIyBBbGwgVmFyaWFibGVzIGR1cmluZyB0aGUgZmlyc3QgbW9udGgKCmBgYHtyIGRhdGEtZXhwbG9yYXRpb24tMjAxOC0xOCwgZXZhbD1GQUxTRSwgaW5jbHVkZT1UUlVFfQpmb3IgKGkgaW4gbmFtZXNfZGlzcGxheSkgewogIGNhdCgiIyMjIyIsIGksICJ7LnVubGlzdGVkIC51bm51bWJlcmVkfSBcbiIpCiAgaWYgKGkgPT0gIm1heGRlcHRoIikgewogICAgcHJpbnQoCiAgICAgIGdncGxvdCgpICsKICAgICAgICBnZW9tX3BvaW50KAogICAgICAgICAgZGF0YSA9IGRhdGFfMjAxOF9maWx0ZXJbZGF5X2RlcGFydHVyZSA8IDMyLCAuKAogICAgICAgICAgICAuaWQsCiAgICAgICAgICAgIGRheV9kZXBhcnR1cmUsCiAgICAgICAgICAgIHRoZXJtb2NsaW5lZGVwdGgKICAgICAgICAgICldLAogICAgICAgICAgYWVzKAogICAgICAgICAgICB4ID0gZGF5X2RlcGFydHVyZSwKICAgICAgICAgICAgeSA9IC10aGVybW9jbGluZWRlcHRoLAogICAgICAgICAgICBjb2xvdXIgPSAiVGhlcm1vY2xpbmUgKG0pIiwKICAgICAgICAgICAgZ3JvdXAgPSBkYXlfZGVwYXJ0dXJlCiAgICAgICAgICApLAogICAgICAgICAgYWxwaGEgPSAuMiwKICAgICAgICAgIHNpemUgPSAuNQogICAgICAgICkgKwogICAgICAgIGdlb21fcG9pbnQoCiAgICAgICAgICBkYXRhID0gZGF0YV8yMDE4X2ZpbHRlcltkYXlfZGVwYXJ0dXJlIDwgMzIsIC4oCiAgICAgICAgICAgIC5pZCwKICAgICAgICAgICAgZGF5X2RlcGFydHVyZSwKICAgICAgICAgICAgZXVwaG90aWNkZXB0aAogICAgICAgICAgKV0sCiAgICAgICAgICBhZXMoCiAgICAgICAgICAgIHggPSBkYXlfZGVwYXJ0dXJlLAogICAgICAgICAgICB5ID0gLWV1cGhvdGljZGVwdGgsCiAgICAgICAgICAgIGNvbG91ciA9ICJFdXBob3RpYyAobSkiLAogICAgICAgICAgICBncm91cCA9IGRheV9kZXBhcnR1cmUKICAgICAgICAgICksCiAgICAgICAgICBhbHBoYSA9IC4yLAogICAgICAgICAgc2l6ZSA9IC41CiAgICAgICAgKSArCiAgICAgICAgc2NhbGVfY29sb3VyX21hbnVhbCgKICAgICAgICAgIHZhbHVlcyA9IGMoCiAgICAgICAgICAgICJUaGVybW9jbGluZSAobSkiID0gInJlZCIsCiAgICAgICAgICAgICJFdXBob3RpYyAobSkiID0gImJsYWNrIgogICAgICAgICAgKSwKICAgICAgICAgIG5hbWUgPSAiWm9uZSIKICAgICAgICApICsKICAgICAgICBuZXdfc2NhbGVfY29sb3IoKSArCiAgICAgICAgZ2VvbV9ib3hwbG90KAogICAgICAgICAgZGF0YSA9IG1lbHQoZGF0YV8yMDE4X2ZpbHRlcltkYXlfZGVwYXJ0dXJlIDwgMzIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAuKC5pZCwgZGF5X2RlcGFydHVyZSwgZ2V0KGkpKV0sIAogICAgICAgICAgICAgICAgICAgICAgaWQudmFycyA9IGMoIi5pZCIsICJkYXlfZGVwYXJ0dXJlIikpLAogICAgICAgICAgYWVzKAogICAgICAgICAgICB4ID0gZGF5X2RlcGFydHVyZSwKICAgICAgICAgICAgeSA9IC12YWx1ZSwKICAgICAgICAgICAgY29sID0gLmlkLAogICAgICAgICAgICBncm91cCA9IGRheV9kZXBhcnR1cmUKICAgICAgICAgICksCiAgICAgICAgICBhbHBoYSA9IDEgLyAxMCwKICAgICAgICAgIHNpemUgPSAuNSwKICAgICAgICAgIHNob3cubGVnZW5kID0gRkFMU0UKICAgICAgICApICsKICAgICAgICBmYWNldF93cmFwKC4gfiAuaWQsIHNjYWxlcyA9ICJmcmVlIikgKwogICAgICAgIGxhYnMoeCA9ICIjIGRheXMgc2luY2UgZGVwYXJ0dXJlIiwgeSA9ICJNYXhpbXVtIERlcHRoIChtKSIpICsKICAgICAgICB0aGVtZV9qam8oKSArCiAgICAgICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIpCiAgICApCiAgfSBlbHNlIHsKICAgIHByaW50KAogICAgICBnZ3Bsb3QoCiAgICAgICAgZGF0YSA9IG1lbHQoZGF0YV8yMDE4X2ZpbHRlcltkYXlfZGVwYXJ0dXJlIDwgMzIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLiguaWQsIGRheV9kZXBhcnR1cmUsIGdldChpKSldLCAKICAgICAgICAgICAgICAgICAgICBpZC52YXJzID0gYygiLmlkIiwgImRheV9kZXBhcnR1cmUiKSksCiAgICAgICAgYWVzKAogICAgICAgICAgeCA9IGRheV9kZXBhcnR1cmUsCiAgICAgICAgICB5ID0gdmFsdWUsCiAgICAgICAgICBjb2xvciA9IC5pZCwKICAgICAgICAgIGdyb3VwID0gZGF5X2RlcGFydHVyZQogICAgICAgICkKICAgICAgKSArCiAgICAgICAgZ2VvbV9ib3hwbG90KAogICAgICAgICAgc2hvdy5sZWdlbmQgPSBGQUxTRSwKICAgICAgICAgIGFscGhhID0gMSAvIDEwLAogICAgICAgICAgc2l6ZSA9IC41CiAgICAgICAgKSArCiAgICAgICAgZmFjZXRfd3JhcCguIH4gLmlkLCBzY2FsZXMgPSAiZnJlZSIpICsKICAgICAgICBsYWJzKHggPSAiIyBkYXlzIHNpbmNlIGRlcGFydHVyZSIsIHkgPSBpKSArCiAgICAgICAgdGhlbWVfampvKCkKICAgICkKICB9CiAgY2F0KCJcbiBcbiIpCn0KYGBgCgojIyMgey51bmxpc3RlZCAudW5udW1iZXJlZCAudGFic2V0IC50YWJzZXQtZmFkZSAudGFic2V0LXBpbGxzfQoKYGBge3IgZGF0YS1leHBsb3JhdGlvbi0yMDE4LTE5LCByZXN1bHRzPSdhc2lzJywgY2FjaGU9VFJVRSwgZWNobz1GQUxTRX0KZm9yIChpIGluIG5hbWVzX2Rpc3BsYXkpIHsKICBjYXQoIiMjIyMiLCBpLCAiey51bmxpc3RlZCAudW5udW1iZXJlZH0gXG4iKQogIGlmIChpID09ICJtYXhkZXB0aCIpIHsKICAgIHByaW50KAogICAgICBnZ3Bsb3QoKSArCiAgICAgICAgZ2VvbV9wb2ludCgKICAgICAgICAgIGRhdGEgPSBkYXRhXzIwMThfZmlsdGVyW2RheV9kZXBhcnR1cmUgPCAzMiwgLigKICAgICAgICAgICAgLmlkLAogICAgICAgICAgICBkYXlfZGVwYXJ0dXJlLAogICAgICAgICAgICB0aGVybW9jbGluZWRlcHRoCiAgICAgICAgICApXSwKICAgICAgICAgIGFlcygKICAgICAgICAgICAgeCA9IGRheV9kZXBhcnR1cmUsCiAgICAgICAgICAgIHkgPSAtdGhlcm1vY2xpbmVkZXB0aCwKICAgICAgICAgICAgY29sb3VyID0gIlRoZXJtb2NsaW5lIChtKSIsCiAgICAgICAgICAgIGdyb3VwID0gZGF5X2RlcGFydHVyZQogICAgICAgICAgKSwKICAgICAgICAgIGFscGhhID0gLjIsCiAgICAgICAgICBzaXplID0gLjUKICAgICAgICApICsKICAgICAgICBnZW9tX3BvaW50KAogICAgICAgICAgZGF0YSA9IGRhdGFfMjAxOF9maWx0ZXJbZGF5X2RlcGFydHVyZSA8IDMyLCAuKAogICAgICAgICAgICAuaWQsCiAgICAgICAgICAgIGRheV9kZXBhcnR1cmUsCiAgICAgICAgICAgIGV1cGhvdGljZGVwdGgKICAgICAgICAgICldLAogICAgICAgICAgYWVzKAogICAgICAgICAgICB4ID0gZGF5X2RlcGFydHVyZSwKICAgICAgICAgICAgeSA9IC1ldXBob3RpY2RlcHRoLAogICAgICAgICAgICBjb2xvdXIgPSAiRXVwaG90aWMgKG0pIiwKICAgICAgICAgICAgZ3JvdXAgPSBkYXlfZGVwYXJ0dXJlCiAgICAgICAgICApLAogICAgICAgICAgYWxwaGEgPSAuMiwKICAgICAgICAgIHNpemUgPSAuNQogICAgICAgICkgKwogICAgICAgIHNjYWxlX2NvbG91cl9tYW51YWwoCiAgICAgICAgICB2YWx1ZXMgPSBjKAogICAgICAgICAgICAiVGhlcm1vY2xpbmUgKG0pIiA9ICJyZWQiLAogICAgICAgICAgICAiRXVwaG90aWMgKG0pIiA9ICJibGFjayIKICAgICAgICAgICksCiAgICAgICAgICBuYW1lID0gIlpvbmUiCiAgICAgICAgKSArCiAgICAgICAgbmV3X3NjYWxlX2NvbG9yKCkgKwogICAgICAgIGdlb21fYm94cGxvdCgKICAgICAgICAgIGRhdGEgPSBtZWx0KGRhdGFfMjAxOF9maWx0ZXJbZGF5X2RlcGFydHVyZSA8IDMyLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLiguaWQsIGRheV9kZXBhcnR1cmUsIGdldChpKSldLCAKICAgICAgICAgICAgICAgICAgICAgIGlkLnZhcnMgPSBjKCIuaWQiLCAiZGF5X2RlcGFydHVyZSIpKSwKICAgICAgICAgIGFlcygKICAgICAgICAgICAgeCA9IGRheV9kZXBhcnR1cmUsCiAgICAgICAgICAgIHkgPSAtdmFsdWUsCiAgICAgICAgICAgIGNvbCA9IC5pZCwKICAgICAgICAgICAgZ3JvdXAgPSBkYXlfZGVwYXJ0dXJlCiAgICAgICAgICApLAogICAgICAgICAgYWxwaGEgPSAxIC8gMTAsCiAgICAgICAgICBzaXplID0gLjUsCiAgICAgICAgICBzaG93LmxlZ2VuZCA9IEZBTFNFCiAgICAgICAgKSArCiAgICAgICAgZmFjZXRfd3JhcCguIH4gLmlkLCBzY2FsZXMgPSAiZnJlZSIpICsKICAgICAgICBsYWJzKHggPSAiIyBkYXlzIHNpbmNlIGRlcGFydHVyZSIsIHkgPSAiTWF4aW11bSBEZXB0aCAobSkiKSArCiAgICAgICAgdGhlbWVfampvKCkgKwogICAgICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iKQogICAgKQogIH0gZWxzZSB7CiAgICBwcmludCgKICAgICAgZ2dwbG90KAogICAgICAgIGRhdGEgPSBtZWx0KGRhdGFfMjAxOF9maWx0ZXJbZGF5X2RlcGFydHVyZSA8IDMyLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC4oLmlkLCBkYXlfZGVwYXJ0dXJlLCBnZXQoaSkpXSwgCiAgICAgICAgICAgICAgICAgICAgaWQudmFycyA9IGMoIi5pZCIsICJkYXlfZGVwYXJ0dXJlIikpLAogICAgICAgIGFlcygKICAgICAgICAgIHggPSBkYXlfZGVwYXJ0dXJlLAogICAgICAgICAgeSA9IHZhbHVlLAogICAgICAgICAgY29sb3IgPSAuaWQsCiAgICAgICAgICBncm91cCA9IGRheV9kZXBhcnR1cmUKICAgICAgICApCiAgICAgICkgKwogICAgICAgIGdlb21fYm94cGxvdCgKICAgICAgICAgIHNob3cubGVnZW5kID0gRkFMU0UsCiAgICAgICAgICBhbHBoYSA9IDEgLyAxMCwKICAgICAgICAgIHNpemUgPSAuNQogICAgICAgICkgKwogICAgICAgIGZhY2V0X3dyYXAoLiB+IC5pZCwgc2NhbGVzID0gImZyZWUiKSArCiAgICAgICAgbGFicyh4ID0gIiMgZGF5cyBzaW5jZSBkZXBhcnR1cmUiLCB5ID0gaSkgKwogICAgICAgIHRoZW1lX2pqbygpCiAgICApCiAgfQogIGNhdCgiXG4gXG4iKQp9CmBgYAoKIyMjIHsudW5saXN0ZWQgLnVubnVtYmVyZWR9CgpgYGB7ciBkYXRhLWV4cGxvcmF0aW9uLTIwMTgtMjAsIGV2YWw9RkFMU0UsIGluY2x1ZGU9VFJVRX0KZm9yIChpIGluIG5hbWVzX2Rpc3BsYXkpIHsKICBjYXQoIiMjIyMiLCBpLCAiey51bmxpc3RlZCAudW5udW1iZXJlZH0gXG4iKQogIHByaW50KAogICAgZ2dwbG90KAogICAgICBkYXRhID0gbWVsdChkYXRhXzIwMThfZmlsdGVyWwogICAgICAgIGRheV9kZXBhcnR1cmUgPCAzMiwKICAgICAgICAuKC5pZCwgZGF5X2RlcGFydHVyZSwgZ2V0KGkpLCBwaGFzZSkKICAgICAgXSwKICAgICAgaWQudmFycyA9IGMoIi5pZCIsICJkYXlfZGVwYXJ0dXJlIiwgInBoYXNlIikKICAgICAgKSwKICAgICAgYWVzKAogICAgICAgIHggPSBkYXlfZGVwYXJ0dXJlLAogICAgICAgIHkgPSB2YWx1ZSwKICAgICAgICBjb2xvciA9IHBoYXNlLAogICAgICAgIGdyb3VwID0gaW50ZXJhY3Rpb24oZGF5X2RlcGFydHVyZSwgcGhhc2UpLAogICAgICApCiAgICApICsKICAgICAgZ2VvbV9ib3hwbG90KAogICAgICAgIGFscGhhID0gMSAvIDEwLAogICAgICAgIHNpemUgPSAuNQogICAgICApICsKICAgICAgZmFjZXRfd3JhcCguIH4gLmlkLCBzY2FsZXMgPSAiZnJlZSIpICsKICAgICAgbGFicyh4ID0gIiMgZGF5cyBzaW5jZSBkZXBhcnR1cmUiLCB5ID0gaSkgKwogICAgICB0aGVtZV9qam8oKSArCiAgICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iKQogICkKICBjYXQoIlxuIFxuIikKfQpgYGAKCiMjIyB7LnVubGlzdGVkIC51bm51bWJlcmVkIC50YWJzZXQgLnRhYnNldC1mYWRlIC50YWJzZXQtcGlsbHN9CgpgYGB7ciBkYXRhLWV4cGxvcmF0aW9uLTIwMTgtMjEsIHJlc3VsdHM9J2FzaXMnLCBjYWNoZT1UUlVFLCBlY2hvPUZBTFNFfQpmb3IgKGkgaW4gbmFtZXNfZGlzcGxheSkgewogIGNhdCgiIyMjIyIsIGksICJ7LnVubGlzdGVkIC51bm51bWJlcmVkfSBcbiIpCiAgcHJpbnQoCiAgICBnZ3Bsb3QoCiAgICAgIGRhdGEgPSBtZWx0KGRhdGFfMjAxOF9maWx0ZXJbCiAgICAgICAgZGF5X2RlcGFydHVyZSA8IDMyLAogICAgICAgIC4oLmlkLCBkYXlfZGVwYXJ0dXJlLCBnZXQoaSksIHBoYXNlKQogICAgICBdLAogICAgICBpZC52YXJzID0gYygiLmlkIiwgImRheV9kZXBhcnR1cmUiLCAicGhhc2UiKQogICAgICApLAogICAgICBhZXMoCiAgICAgICAgeCA9IGRheV9kZXBhcnR1cmUsCiAgICAgICAgeSA9IHZhbHVlLAogICAgICAgIGNvbG9yID0gcGhhc2UsCiAgICAgICAgZ3JvdXAgPSBpbnRlcmFjdGlvbihkYXlfZGVwYXJ0dXJlLCBwaGFzZSksCiAgICAgICkKICAgICkgKwogICAgICBnZW9tX2JveHBsb3QoCiAgICAgICAgYWxwaGEgPSAxIC8gMTAsCiAgICAgICAgc2l6ZSA9IC41CiAgICAgICkgKwogICAgICBmYWNldF93cmFwKC4gfiAuaWQsIHNjYWxlcyA9ICJmcmVlIikgKwogICAgICBsYWJzKHggPSAiIyBkYXlzIHNpbmNlIGRlcGFydHVyZSIsIHkgPSBpKSArCiAgICAgIHRoZW1lX2pqbygpICsKICAgICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIpCiAgKQogIGNhdCgiXG4gXG4iKQp9CmBgYAoKIyMjIENvcnJlbGF0aW9uCgpDYW4gd2UgZmluZCBuaWNlIGNvcnJlbGF0aW9uPwogIApgYGB7ciBkYXRhLWV4cGxvcmF0aW9uLTIwMTgtMjIsIGZpZy5jYXA9IkNvcnJlbGF0aW9uIG1hdHJpeCAoY3Jvc3NlcyBpbmRpY2F0ZSBub24gc2lnbmlmaWNhbnQgY29ycmVsYXRpb24pIiwgZmlnLndpZHRoPTEwLCBmaWcuaGVpZ2h0PTEwfQojIGNvbXB1dGUgY29ycmVsYXRpb24KY29ycl8yMDE4IDwtIHJvdW5kKGNvcihkYXRhXzIwMThfZmlsdGVyWywgbmFtZXNfZGlzcGxheSwgd2l0aCA9IEZdLAogICAgICAgICAgICAgICAgICAgICAgIHVzZSA9ICJwYWlyd2lzZS5jb21wbGV0ZS5vYnMiCiksIDEpCgojIHJlcGxhY2UgTkEgdmFsdWUgYnkgMApjb3JyXzIwMThbaXMubmEoY29ycl8yMDE4KV0gPC0gMAoKIyBjb21wdXRlIHBfdmFsdWVzCmNvcnJfcF8yMDE4IDwtIGNvcl9wbWF0KGRhdGFfMjAxOF9maWx0ZXJbLCBuYW1lc19kaXNwbGF5LCB3aXRoID0gRl0pCgojIHJlcGxhY2UgTkEgdmFsdWUgYnkgMApjb3JyX3BfMjAxOFtpcy5uYShjb3JyX3BfMjAxOCldIDwtIDEKCiMgZGlzcGxheQpnZ2NvcnJwbG90KAogIGNvcnJfMjAxOCwKICBwLm1hdCA9IGNvcnJfcF8yMDE4LAogIGhjLm9yZGVyID0gVFJVRSwKICBtZXRob2QgPSAiY2lyY2xlIiwKICB0eXBlID0gImxvd2VyIiwKICBnZ3RoZW1lID0gdGhlbWVfampvKCksCiAgc2lnLmxldmVsID0gMC4wNSwKICBjb2xvcnMgPSAgYygiIzAwQUZCQiIsICIjRTdCODAwIiwgIiNGQzRFMDciKQopCmBgYAoKQW5vdGhlciB3YXkgdG8gc2VlIGl0OgogIApgYGB7ciBkYXRhLWV4cGxvcmF0aW9uLTIwMTgtMjN9CiMgZmxhdHRlbiBjb3JyZWxhdGlvbiBtYXRyaXgKY29yX3Jlc3VsdF8yMDE4IDwtIGZsYXRfY29yX21hdChjb3JyXzIwMTgsIGNvcnJfcF8yMDE4KQoKIyBrZWVwIG9ubHkgdGhlIG9uZSBhYm92ZSAuNwpjb3JfcmVzdWx0XzIwMThbY29yID49IC43LCBdW29yZGVyKC1hYnMoY29yKSldICU+JQogIHNhYmxlKGNhcHRpb24gPSAiUGFpcndpc2UgY29ycmVsYXRpb24gYWJvdmUgMC43NSBhbmQgYXNzb2NpYXRlZCBwLXZhbHVlcyIpCmBgYAoKPiBJIGd1ZXNzIG5vdGhpbmcgdW5leHBlY3RlZCBoZXJlLCBJJ2xsIGhhdmUgdG8gY2hlY2sgd2l0aCBQYXRyaWNrIGFib3V0IHRoZSBlZmZpY2llbmN5IDspCgojIyBEaXZlIFR5cGUKCmBgYHtyIGRhdGEtZXhwbG9yYXRpb24tMjAxOC0yNCwgZmlnLmNhcD0iUHJvcG9ydGlvbiBkaXZlIHR5cGVzIn0KIyBkYXRhc2V0IHRvIHBsb3QgcHJvcG9ydGlvbmFsIGFyZWEgcGxvdApkYXRhXzIwMThfZmlsdGVyWywgc3VtX2lkIDo9IC5OLCBieSA9IC4oLmlkLCBkYXlfZGVwYXJ0dXJlKV0gJT4lCiAgLlssIHN1bV9pZF9kYXlzIDo9IC5OLCBieSA9IC4oLmlkLCBkYXlfZGVwYXJ0dXJlLCBkaXZldHlwZSldICU+JQogIC5bLCBwcm9wIDo9IHN1bV9pZF9kYXlzIC8gc3VtX2lkXQpkYXRhUGxvdCA8LSB1bmlxdWUoZGF0YV8yMDE4X2ZpbHRlclssIC4ocHJvcCwgLmlkLCBkaXZldHlwZSwgZGF5X2RlcGFydHVyZSldKQoKIyBhcmVhIHBsb3QKZ2dwbG90KGRhdGFQbG90LCBhZXMoCiAgeCA9IGFzLm51bWVyaWMoZGF5X2RlcGFydHVyZSksCiAgeSA9IHByb3AsCiAgZmlsbCA9IGFzLmNoYXJhY3RlcihkaXZldHlwZSkKKSkgKwogIGdlb21fYXJlYShhbHBoYSA9IDAuNiwgc2l6ZSA9IDEpICsKICBmYWNldF93cmFwKC5pZCB+IC4sIHNjYWxlcyA9ICJmcmVlIikgKwogIHRoZW1lX2pqbygpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIikgKwogIGxhYnMoeCA9ICIjIG9mIGRheXMgc2luY2UgZGVwYXJ0dXJlIiwgCiAgICAgICB5ID0gIlByb3BvcnRpb24gb2YgZGl2ZXMiLCAKICAgICAgIGZpbGwgPSAiRGl2ZSB0eXBlcyIpCmBgYAoKIyMgRGl2ZSBkdXJhdGlvbiAqdnMuKiBNYXhpbXVtIGRlcHRoIHsudGFic2V0fQoKIyMjIENvbG9yZWQgYnkgSUQKCmBgYHtyIGRhdGEtZXhwbG9yYXRpb24tMjAxOC0yNSwgZmlnLmNhcD0iRGl2ZSBkdXJhdGlvbiB2cy4gTWF4aW11bSBEZXB0aCBjb2xvcmVkIDIwMTgtaW5kaXZpZHVhbHMifQojIHBsb3QKZ2dwbG90KGRhdGEgPSBkYXRhXzIwMThfZmlsdGVyLCBhZXMoeSA9IGRkdXJhdGlvbiwgeCA9IG1heGRlcHRoLCBjb2wgPSAuaWQpKSArCiAgZ2VvbV9wb2ludChzaXplID0gLjUsIGFscGhhID0gLjEsIHNob3cubGVnZW5kID0gRkFMU0UpICsKICBmYWNldF93cmFwKC5pZCB+IC4pICsKICBsYWJzKHggPSAiTWF4aW11bSBkZXB0aCAobSkiLCB5ID0gIkRpdmUgZHVyYXRpb24gKHMpIikgKwogIHRoZW1lX2pqbygpCmBgYAoKIyMjIENvbG9yZWQgYnkgRGl2ZSBUeXBlCgpgYGB7ciBkYXRhLWV4cGxvcmF0aW9uLTIwMTgtMjYsIGZpZy5jYXA9IkRpdmUgZHVyYXRpb24gdnMuIE1heGltdW0gRGVwdGggY29sb3JlZCBieSBEaXZlIFR5cGUifQojIHBsb3QKZ2dwbG90KGRhdGEgPSBkYXRhXzIwMThfZmlsdGVyLCBhZXMoeSA9IGRkdXJhdGlvbiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHggPSBtYXhkZXB0aCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbCA9IGRpdmV0eXBlKSkgKwogIGdlb21fcG9pbnQoc2l6ZSA9IC41LCBhbHBoYSA9IC4xKSArCiAgZmFjZXRfd3JhcCguaWQgfiAuKSArCiAgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2xlZ2VuZChvdmVycmlkZS5hZXMgPSBsaXN0KHNpemUgPSA1LCBhbHBoYSA9IDEpKSkgKwogIGxhYnMoeCA9ICJNYXhpbXVtIGRlcHRoIChtKSIsIHkgPSAiRGl2ZSBkdXJhdGlvbiAocykiKSArCiAgdGhlbWVfampvKCkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iKQpgYGAKCiMjIyBDb2xvcmVkIGJ5ICMgZGF5cyBzaW5jZSBkZXBhcnR1cmUKCmBgYHtyIGRhdGEtZXhwbG9yYXRpb24tMjAxOC0yNywgZmlnLmNhcD0iRGl2ZSBkdXJhdGlvbiB2cy4gTWF4aW11bSBEZXB0aCBjb2xvcmVkIGJ5ICMgZGF5cyBzaW5jZSBkZXBhcnR1cmUifQojIHBsb3QKZ2dwbG90KGRhdGEgPSBkYXRhXzIwMThfZmlsdGVyWywgcHJvcF90cmFjayA6PSAoZGF5X2RlcGFydHVyZSAqIDEwMCkgLyBtYXgoZGF5X2RlcGFydHVyZSksIGJ5ID0gLmlkXSwgCiAgICAgICBhZXMoeSA9IGRkdXJhdGlvbiwgeCA9IG1heGRlcHRoLCBjb2wgPSBwcm9wX3RyYWNrKSkgKwogIGdlb21fcG9pbnQoc2l6ZSA9IC41LCBhbHBoYSA9IC4xKSArCiAgZmFjZXRfd3JhcCguaWQgfiAuKSArCiAgbGFicyh4ID0gIk1heGltdW0gZGVwdGggKG0pIiwgCiAgICAgICB5ID0gIkRpdmUgZHVyYXRpb24gKHMpIiwgCiAgICAgICBjb2wgPSAiUHJvcG9ydGlvbiBvZiBjb21wbGV0ZWQgdHJhY2sgKCUpIikgKwogIHNjYWxlX2NvbG9yX2NvbnRpbnVvdXModHlwZSA9ICJ2aXJpZGlzIikgKwogIHRoZW1lX2pqbygpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIikKYGBgCgojIyMgQ29sb3JlZCBieSBwaGFzZXMgb2YgZGF5CgpgYGB7ciBkYXRhLWV4cGxvcmF0aW9uLTIwMTgtMjgsIGZpZy5jYXA9IkRpdmUgZHVyYXRpb24gdnMuIE1heGltdW0gRGVwdGggY29sb3JlZCBieSBwaGFzZXMgb2YgdGhlIGRheSJ9CiMgcGxvdApnZ3Bsb3QoZGF0YSA9IGRhdGFfMjAxOF9maWx0ZXIsIGFlcyh5ID0gZGR1cmF0aW9uLCB4ID0gbWF4ZGVwdGgsIGNvbCA9IHBoYXNlKSkgKwogIGdlb21fcG9pbnQoc2l6ZSA9IC41LCBhbHBoYSA9IC4xKSArCiAgZmFjZXRfd3JhcCguaWQgfiAuKSArCiAgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2xlZ2VuZChvdmVycmlkZS5hZXMgPSBsaXN0KHNpemUgPSA1LCBhbHBoYSA9IDEpKSkgKwogIGxhYnMoeCA9ICJNYXhpbXVtIGRlcHRoIChtKSIsIAogICAgICAgeSA9ICJEaXZlIGR1cmF0aW9uIChzKSIsIAogICAgICAgY29sID0gIlBoYXNlcyBvZiB0aGUgZGF5IikgKwogIHRoZW1lX2pqbygpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIikKYGBgCgo+IFRoZXJlIHNlZW1zIHRvIGJlIGEgKnBhdGNoKiBmb3IgaGlnaCBkZXB0aHMgKGVzcGVjaWFsbHkgdmlzaWJsZSBmb3IgYGluZDIwMTgwNzBgKSwgYnV0IEkgZG9uJ3Qga25vdyB3aGF0IGl0IGNvdWxkIGJlIGxpbmtlZCB0by4uLgoKIyMgRHJpZnQgUmF0ZQoKPiBJbiB0aGUgZm9sbG93aW5nIGdyYXBoczoKPgo+ICogYGRyaWZ0cmF0ZWAgaXMgY2FsY3VsYXRlZCB1c2luZyBvbmx5IGBkaXZldHlwZSA9PSAiMjogZHJpZnQiYAo+ICogd2hlcmVhcyBhbGwgdGhlIG90aGVycyB2YXJpYWJsZXMgYXJlIGNhbGN1bGF0ZWQgYWxsIGRpdmVzIGNvbnNpZGVyZWQKCmBgYHtyIGRhdGEtZXhwbG9yYXRpb24tMjAxOC0yOX0KIyBidWlsZCBkYXRhc2V0CmRhdGFQbG90IDwtIGRhdGFfMjAxOF9maWx0ZXJbZGl2ZXR5cGUgPT0gIjI6IGRyaWZ0IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIG1lZGlhbiBkcmlmdCByYXRlIGZvciBkcmlmdCBkaXZlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLihkcmlmdHJhdGUgPSBtZWRpYW4oZHJpZnRyYXRlLCBuYS5ybSA9IFQpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieSA9IC4oLmlkLCBkYXlfZGVwYXJ0dXJlKQpdW2RhdGFfMjAxOF9maWx0ZXJbLAogICAgICAgICAgICAgICAgICAgLigKICAgICAgICAgICAgICAgICAgICAgIyBtZWRpYW4gZGl2ZSBkdXJhdGlvbiBhbGwgZGl2ZXMgY29uc2lkZXJlZAogICAgICAgICAgICAgICAgICAgICBkZHVyYXRpb24gPSBtZWRpYW4oZGR1cmF0aW9uLCBuYS5ybSA9IFQpLAogICAgICAgICAgICAgICAgICAgICAjIG1lZGlhbiBtYXggZGVwdGggYWxsIGRpdmVzIGNvbnNpZGVyZWQKICAgICAgICAgICAgICAgICAgICAgbWF4ZGVwdGggPSBtZWRpYW4obWF4ZGVwdGgsIG5hLnJtID0gVCksCiAgICAgICAgICAgICAgICAgICAgICMgbWVkaWFuIGJvdHRvbSBkaXZlcyBhbGwgZGl2ZXMgY29uc2lkZXJlZAogICAgICAgICAgICAgICAgICAgICBib3R0dGltZSA9IG1lZGlhbihib3R0dGltZSwgbmEucm0gPSBUKQogICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgICAgICAgICAgIGJ5ID0gLiguaWQsIGRheV9kZXBhcnR1cmUpCl0sCm9uID0gYygiLmlkIiwgImRheV9kZXBhcnR1cmUiKQpdCmBgYAoKYGBge3IgZGF0YS1leHBsb3JhdGlvbi0yMDE4LTMwLCBmaWcuY2FwPSJEcmlmdCByYXRlIHZzLiBCb3R0b20gdGltZSJ9CiMgcGxvdApnZ3Bsb3QoZGF0YVBsb3QsIGFlcyh4ID0gYm90dHRpbWUsIHkgPSBkcmlmdHJhdGUsIGNvbCA9IC5pZCkpICsKICBnZW9tX3BvaW50KHNpemUgPSAuNSwgYWxwaGEgPSAuNSkgKwogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIpICsKICBndWlkZXMoY29sb3IgPSAibm9uZSIpICsKICBmYWNldF93cmFwKC5pZCB+IC4pICsKICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCA3MDApKSArCiAgbGFicyh4ID0gIkRhaWx5IG1lZGlhbiBCb3R0b20gdGltZSAocykiLCAKICAgICAgIHkgPSAiRGFpbHkgbWVkaWFuIGRyaWZ0IHJhdGUgKG0ucy0xKSIpICsKICB0aGVtZV9qam8oKQpgYGAKCmBgYHtyIGRhdGEtZXhwbG9yYXRpb24tMjAxOC0zMSwgZmlnLmNhcD0iRHJpZnQgcmF0ZSB2cy4gTWF4aW11bSBkZXB0aCJ9CiMgcGxvdApnZ3Bsb3QoZGF0YVBsb3QsIGFlcyh4ID0gbWF4ZGVwdGgsIHkgPSBkcmlmdHJhdGUsIGNvbCA9IC5pZCkpICsKICBnZW9tX3BvaW50KHNpemUgPSAuNSwgYWxwaGEgPSAuNSkgKwogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIpICsKICBndWlkZXMoY29sb3IgPSAibm9uZSIpICsKICBmYWNldF93cmFwKC5pZCB+IC4pICsKICBsYWJzKHggPSAiRGFpbHkgbWVkaWFuIE1heGltdW0gZGVwdGggKG0pIiwgCiAgICAgICB5ID0gIkRhaWx5IG1lZGlhbiBkcmlmdCByYXRlIChtLnMtMSkiKSArCiAgdGhlbWVfampvKCkKYGBgCgpgYGB7ciBkYXRhLWV4cGxvcmF0aW9uLTIwMTgtMzIsIGZpZy5jYXA9IkRyaWZ0IHJhdGUgdnMuIERpdmUgZHVyYXRpb24ifQojIHBsb3QKZ2dwbG90KGRhdGFQbG90LCBhZXMoeCA9IGRkdXJhdGlvbiwgeSA9IGRyaWZ0cmF0ZSwgY29sID0gLmlkKSkgKwogIGdlb21fcG9pbnQoc2l6ZSA9IC41LCBhbHBoYSA9IC41KSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIikgKwogIGd1aWRlcyhjb2xvciA9ICJub25lIikgKwogIGZhY2V0X3dyYXAoLmlkIH4gLikgKwogIGxhYnMoeCA9ICJEYWlseSBtZWRpYW4gRGl2ZSBkdXJhdGlvbiAocykiLCAKICAgICAgIHkgPSAiRGFpbHkgbWVkaWFuIGRyaWZ0IHJhdGUgKG0ucy0xKSIpICsKICB0aGVtZV9qam8oKQpgYGAKCiMjIEJlaGF2aW9yYWwgQWVyb2JpYyBEaXZlIExpbWl0IChiQURMKQoKIyMjIFtDb29rIGV0IGFsICgyMDA4KV0oaHR0cHM6Ly93d3cuc2NpZW5jZWRpcmVjdC5jb20vc2NpZW5jZS9hcnRpY2xlL3BpaS9TMDAwMzM0NzIwODAwMTM2WD92aWElM0RpaHViKQoKYGBge3IgZGF0YS1leHBsb3JhdGlvbi0yMDE4LTMzLCBmaWcuY2FwPSJQb3N0LWRpdmUgZHVyYXRpb24gdnMuIGRpdmUgZHVyYXRpb24ifQojIGRpdmUgZHVyYXRpb24gdnMgcGRpIGJ5IGRheXMKZ2dwbG90KGRhdGEgPSBkYXRhXzIwMThfZmlsdGVyW3BkaSA8IDMwMCwgXSwgYWVzKAogIHggPSBkZHVyYXRpb24sCiAgeSA9IHBkaSwKICBjb2xvciA9IC5pZCwKICBncm91cCA9IGRkdXJhdGlvbiwKICBmaWxsID0gIm5vbmUiCikpICsKICBnZW9tX2JveHBsb3Qoc2hvdy5sZWdlbmQgPSBGQUxTRSwgb3V0bGllci5hbHBoYSA9IDAuMDUsIGFscGhhID0gMCkgKwogIGxhYnMoeCA9ICJEaXZlIGR1cmF0aW9uIChzKSIsIHkgPSAiUG9zdC1kaXZlIGR1cmF0aW9uIChzKSIpICsKICBmYWNldF93cmFwKC4gfiAuaWQsIHNjYWxlcyA9ICJmcmVlX3giKSArCiAgdGhlbWVfampvKCkKYGBgCgpgYGB7ciBkYXRhLWV4cGxvcmF0aW9uLTIwMTgtMzQsIGZpZy5jYXA9IlBvc3QtZGl2ZSBkdXJhdGlvbiB2cy4gZGl2ZSBkdXJhdGlvbiAocmF3IGRhdGEpIn0KIyBkaXZlIGR1cmF0aW9uIHZzIHBkaSBieSBkYXlzCmdncGxvdChkYXRhID0gZGF0YV8yMDE4X2ZpbHRlcltwZGkgPCAzMDAsXSwgYWVzKHggPSBkZHVyYXRpb24sIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB5ID0gcGRpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb3IgPSAuaWQpKSArCiAgZ2VvbV9wb2ludChzaG93LmxlZ2VuZCA9IEZBTFNFLCBhbHBoYSA9IDAuMDUpICsKICBnZW9tX3Ntb290aCgKICAgIG1ldGhvZCA9ICJnYW0iLAogICAgc2hvdy5sZWdlbmQgPSBGQUxTRSwKICAgIGNvbCA9ICJibGFjayIsCiAgICBsaW5ldHlwZSA9ICJkYXNoZWQiCiAgKSArCiAgbGFicyh4ID0gIkRpdmUgZHVyYXRpb24gKHMpIiwgeSA9ICJQb3N0LWRpdmUgZHVyYXRpb24gKHMpIikgKwogIGZhY2V0X3dyYXAoLiB+IC5pZCwgc2NhbGVzID0gImZyZWVfeCIpICsKICB0aGVtZV9qam8oKQpgYGAKYGBge3IgZGF0YS1leHBsb3JhdGlvbi0yMDE4LTM1LCBmaWcuY2FwPSJQb3N0LWRpdmUgZHVyYXRpb24gLyBkaXZlIGR1cmF0aW9uIHJhdGlvIHZzLiBkYXkgc2luY2UgZGVwYXJ0dXJlIn0KIyBkaXZlIGR1cmF0aW9uIHZzIHBkaSBieSBkYXlzCmdncGxvdCgKICBkYXRhID0gZGF0YV8yMDE4X2ZpbHRlcltwZGkgPCAzMDAsIC4oLmlkLCBwZGlfcmF0aW8gPSBwZGkgLyBkZHVyYXRpb24sIGRheV9kZXBhcnR1cmUpXSwKICBhZXMoCiAgICB4ID0gZGF5X2RlcGFydHVyZSwKICAgIHkgPSBwZGlfcmF0aW8sCiAgICBjb2xvciA9IC5pZCwKICAgIGdyb3VwID0gZGF5X2RlcGFydHVyZSwKICAgIGZpbGwgPSAibm9uZSIKICApCikgKwogIGdlb21fYm94cGxvdChzaG93LmxlZ2VuZCA9IEZBTFNFLAogICAgICAgICAgICAgICBvdXRsaWVyLmFscGhhID0gMC4wNSwKICAgICAgICAgICAgICAgYWxwaGEgPSAwKSArCiAgbGFicyh4ID0gIiMgZGF5cyBzaW5jZSBkZXBhcnR1cmUiLCB5ID0gIlBvc3QtZGl2ZSAvIERpdmUgZHVyYXRpb24gcmF0aW8iKSArCiAgZmFjZXRfd3JhcCguIH4gLmlkLCBzY2FsZXMgPSAiZnJlZV94IikgKwogICMgem9vbQogIGNvb3JkX2NhcnRlc2lhbih5bGltID0gYygwLCAwLjQpKSArCiAgdGhlbWVfampvKCkKYGBgCgojIyMgW1NoZXJvIGV0ICphbC4qICgyMDE4KV0oaHR0cHM6Ly93d3cucmVzZWFyY2hnYXRlLm5ldC9wdWJsaWNhdGlvbi8yMjI2ODMwNDJfVG9fYnJlYXRoZV9vcl9ub3RfdG9fYnJlYXRoZV9PcHRpbWFsX2JyZWF0aGluZ19hZXJvYmljX2RpdmVfbGltaXRfYW5kX294eWdlbl9zdG9yZXNfaW5fZGVlcC1kaXZpbmdfYmx1ZS1leWVkX3NoYWdzKQoKQmFzZWQgb24gW1NoZXJvIGV0ICphbC4qICgyMDE4KV0oaHR0cHM6Ly93d3cucmVzZWFyY2hnYXRlLm5ldC9wdWJsaWNhdGlvbi8yMjI2ODMwNDJfVG9fYnJlYXRoZV9vcl9ub3RfdG9fYnJlYXRoZV9PcHRpbWFsX2JyZWF0aGluZ19hZXJvYmljX2RpdmVfbGltaXRfYW5kX294eWdlbl9zdG9yZXNfaW5fZGVlcC1kaXZpbmdfYmx1ZS1leWVkX3NoYWdzKSwgd2UgZGVjaWRlZCB0byBsb29rIGF0IHRoZSAqYkFETCogYXMgdGhlIDk1dGggcGVyY2VudGlsZSBvZiBkaXZlIGR1cmF0aW9uIGVhY2ggZGF5LCBmb3IgdGhvc2Ugd2l0aCAkbiBcZ2VxIDUwJC4gVGhpcyB0aHJlc2hvbGQgd2FzIGNob3NlbiBmb2xsb3dpbmcgdGhpcyBmaWd1cmU6CgpgYGB7ciBkYXRhLWV4cGxvcmF0aW9uLTIwMTgtMzYsIGZpZy5jYXA9IkRpc3RyaWJ1dGlvbiBvZiB0aGUgbnVtYmVyIG9mIGRpdmVzIGVhY2ggZGF5LiBUaGUgdGhyZXNob2xkIHVzZWQgdG8gY2FsY3VsYXRlIGJBREwgaXMgZml4ZWQgYXQgNTAgZGl2ZXMgcGVyIGRheS4iLCBmaWcuaGVpZ2h0PTN9CmdncGxvdChkYXRhXzIwMThfZmlsdGVyWywuKG5iX2RpdmVzID0gLk4pLCAKICAgICAgICAgICAgICAgICAgICAgICAgYnkgPSAuKC5pZCwgZGF5X2RlcGFydHVyZSldLCAKICAgICAgIGFlcyh4PW5iX2RpdmVzLCBmaWxsPS5pZCkpICsKICBnZW9tX2hpc3RvZ3JhbShzaG93LmxlZ2VuZCA9IEZBTFNFKSArIAogIGZhY2V0X2dyaWQoLn4uaWQpICsKICBsYWJzKHk9IiMgb2YgZGF5cyIsIHggPSAiIyBvZiBkaXZlcyBwZXIgZGF5IikgKwogIHRoZW1lX2pqbygpCmBgYAoKYGBge3IgZGF0YS1leHBsb3JhdGlvbi0yMDE4LTM3LCBmaWcuY2FwPSJCZWhhdmlvcmFsIEFETCB2cy4gZHJpZnQgcmF0ZSBhbG9uZyBhbmltYWxzJyB0cmlwIChBbSBJIHRoZSBvbmx5IG9uZSBzZWVpbmcgc29tZSBraW5kIG9mIHJlbGF0aW9uc2hpcD8pIn0KIyBzZWxlY3QgZGF5IHRoYXQgaGF2ZSBhdCBsZWFzdCA1MCBkaXZlcwpkYXlzX3RvX2tlZXAgPSBkYXRhXzIwMThfZmlsdGVyWywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAuKG5iX2RpdmVzID0gLk4pLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5ID0gLiguaWQsIGRheV9kZXBhcnR1cmUpXSAlPiUKICAuW25iX2RpdmVzID49IDUwLF0KCiMga2VlcCBvbmx5IHRob3NlIGRheXMKZGF0YV8yMDE4X2ZpbHRlcl9jb21wbGV0ZV9kYXkgPSBtZXJnZShkYXRhXzIwMThfZmlsdGVyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRheXNfdG9fa2VlcCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieSA9IGMoIi5pZCIsICJkYXlfZGVwYXJ0dXJlIikpCgojIGRhdGEgcGxvdApkYXRhUGxvdCA9IGRhdGFfMjAxOF9maWx0ZXJfY29tcGxldGVfZGF5WywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAuKGJhZGwgPSBxdWFudGlsZShkZHVyYXRpb24sIDAuOTUpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieSA9IC4oLmlkLCBkYXlfZGVwYXJ0dXJlKV0KCiMgY29tYmluZSB0d28gZGF0YXNldHMgdG8gYmUgYWJsZSB0byB1c2UgYSBzZWNvbmQgYXhpcwojIGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzQ5MTg1NTgzL3R3by15LWF4ZXMtd2l0aC1kaWZmZXJlbnQtc2NhbGVzLWZvci10d28tZGF0YXNldHMtaW4tZ2dwbG90MgpkYXRhTWVnYVBsb3QgPSByYmluZChkYXRhXzIwMThfZmlsdGVyX2NvbXBsZXRlX2RheVtkaXZldHlwZSA9PSAiMjogZHJpZnQiXSAlPiUKICAgICAgICAgICAgICAgICAgICAgICAuWywgLih3ID0gLmlkLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHkgPSBkcmlmdHJhdGUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeCA9IGRheV9kZXBhcnR1cmUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeiA9ICJzZWNvbmRfcGxvdCIpXSwKICAgICAgICAgICAgICAgICAgICAgZGF0YVBsb3RbLCAuKAogICAgICAgICAgICAgICAgICAgICAgIHcgPSAuaWQsCiAgICAgICAgICAgICAgICAgICAgICAgIyB0cmlja3kgb25lCiAgICAgICAgICAgICAgICAgICAgICAgeSA9IChiYWRsIC8gMTAwMCkgLSAxLAogICAgICAgICAgICAgICAgICAgICAgIHggPSBkYXlfZGVwYXJ0dXJlLAogICAgICAgICAgICAgICAgICAgICAgIHogPSAiZmlyc3RfcGxvdCIKICAgICAgICAgICAgICAgICAgICAgKV0pCgojIHBsb3QKZ2dwbG90KCkgKwogIGdlb21fcG9pbnQoCiAgICBkYXRhID0gZGF0YU1lZ2FQbG90W3ogPT0gInNlY29uZF9wbG90IiwgXSwKICAgIGFlcyh4ID0geCwgeSA9IHkpLAogICAgYWxwaGEgPSAxIC8gMTAsCiAgICBzaXplID0gMC41LAogICAgY29sb3IgPSAiZ3JleTQwIiwKICAgIHNob3cubGVnZW5kID0gRkFMU0UKICApICsKICBnZW9tX3BhdGgoZGF0YSA9IGRhdGFNZWdhUGxvdFt6ID09ICJmaXJzdF9wbG90IiwgXSwKICAgICAgICAgICAgYWVzKHggPSB4LCB5ID0geSwgY29sb3IgPSB3KSwKICAgICAgICAgICAgc2hvdy5sZWdlbmQgPSBGQUxTRSkgKwogIHNjYWxlX3lfY29udGludW91cygKICAgICMgRmVhdHVyZXMgb2YgdGhlIGZpcnN0IGF4aXMKICAgIG5hbWUgPSAiRHJpZnQgcmF0ZSAobS9zKSIsCiAgICAjIEFkZCBhIHNlY29uZCBheGlzIGFuZCBzcGVjaWZ5IGl0cyBmZWF0dXJlcwogICAgc2VjLmF4aXMgPSBzZWNfYXhpcyggfiAoLiAqIDEwMDApICsgMTAwMCwgCiAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lID0gIkJlaGF2aW9yYWwgQWVyb2JpYyBEaXZlIExpbWl0IChzKSIpCiAgKSArCiAgbGFicyh4ID0gIiMgZGF5cyBzaW5jZSBkZXBhcnR1cmUiKSArCiAgZmFjZXRfd3JhcCh3IH4gLikgKwogIHRoZW1lX2pqbygpCmBgYAoKPiBMb29raW5nIGF0IHRoaXMgZ3JhcGgsIEkgd2FudCB0byBiZWxpZXZlIHRoYXQgdGhlcmUgaXMgc29tZSBraW5kIG9mIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHRoZSAqYkFETCogYXMgZGVmaW5lZCBieSBbU2hlcm8gZXQgKmFsLiogKDIwMTgpXShodHRwczovL3d3dy5yZXNlYXJjaGdhdGUubmV0L3B1YmxpY2F0aW9uLzIyMjY4MzA0Ml9Ub19icmVhdGhlX29yX25vdF90b19icmVhdGhlX09wdGltYWxfYnJlYXRoaW5nX2Flcm9iaWNfZGl2ZV9saW1pdF9hbmRfb3h5Z2VuX3N0b3Jlc19pbl9kZWVwLWRpdmluZ19ibHVlLWV5ZWRfc2hhZ3MpIGFuZCB0aGUgZHJpZnQgcmF0ZSAoYW5kIHNvIGJ1eW9hbmN5KS4KCmBgYHtyIGRhdGEtZXhwbG9yYXRpb24tMjAxOC0zOH0KIyBnZXQgYmFkbApkYXRhcGxvdF8xID0gZGF0YV8yMDE4X2ZpbHRlcl9jb21wbGV0ZV9kYXlbLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAuKGJhZGwgPSBxdWFudGlsZShkZHVyYXRpb24sIDAuOTUpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnkgPSAuKC5pZCwgZGF5X2RlcGFydHVyZSldCiMgZ2V0IGRyaWZ0cmF0ZQpkYXRhcGxvdF8yID0gZGF0YV8yMDE4X2ZpbHRlcl9jb21wbGV0ZV9kYXlbZGl2ZXR5cGUgPT0gIjI6IGRyaWZ0IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLihkcmlmdHJhdGUgPSBtZWRpYW4oZHJpZnRyYXRlKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5ID0gLiguaWQsIGRheV9kZXBhcnR1cmUpXQoKIyBtZXJnZQpkYXRhUGxvdCA9IG1lcmdlKGRhdGFwbG90XzEsCiAgICAgICAgICAgICAgICAgZGF0YXBsb3RfMiwKICAgICAgICAgICAgICAgICBieSA9IGMoIi5pZCIsICJkYXlfZGVwYXJ0dXJlIiksCiAgICAgICAgICAgICAgICAgYWxsID0gVFJVRSkKCiMgcGxvdApnZ3Bsb3QoZGF0YSA9IGRhdGFQbG90LCBhZXMoeCA9IGJhZGwsIHkgPSBkcmlmdHJhdGUsIGNvbCA9IC5pZCkpICsKICBnZW9tX3BvaW50KHNob3cubGVnZW5kID0gRkFMU0UpICsKICBmYWNldF93cmFwKC5pZH4uLCBzY2FsZXMgPSAiZnJlZSIpICsKICB0aGVtZV9qam8oKQpgYGAKCiMjIyB7LnVubGlzdGVkIC51bm51bWJlcmVkIC50YWJzZXQgLnRhYnNldC1mYWRlIC50YWJzZXQtcGlsbHN9CgojIyMjIGluZF8yMDE4MDcwIHsudW5saXN0ZWQgLnVubnVtYmVyZWR9CgpgYGB7ciBkYXRhLWV4cGxvcmF0aW9uLTIwMTgtMzl9CiMgaW5kXzIwMTgwNzAKcGxvdF9seSgKICB4ID0gZGF0YVBsb3RbLmlkID09ICJpbmRfMjAxODA3MCIsIGJhZGxdLAogIHkgPSBkYXRhUGxvdFsuaWQgPT0gImluZF8yMDE4MDcwIiwgZGF5X2RlcGFydHVyZV0sCiAgeiA9IGRhdGFQbG90Wy5pZCA9PSAiaW5kXzIwMTgwNzAiLCBkcmlmdHJhdGVdLAogIHR5cGUgPSAic2NhdHRlcjNkIiwKICBtb2RlID0gIm1hcmtlcnMiLAogIG1hcmtlciA9IGxpc3Qoc2l6ZSA9IDIpLAogIGNvbG9yID0gZGF0YVBsb3RbLmlkID09ICJpbmRfMjAxODA3MCIsIGRheV9kZXBhcnR1cmVdCikgJT4lIAogIGxheW91dChzY2VuZSA9IGxpc3QoeGF4aXMgPSBsaXN0KHRpdGxlID0gJ0JlaGF2aW9yYWwgQURMJyksCiAgICAgICAgICAgICAgICAgICAgICB5YXhpcyA9IGxpc3QodGl0bGUgPSAnIyBkYXlzIHNpbmNlIGRlcGFydHVyZScpLAogICAgICAgICAgICAgICAgICAgICAgemF4aXMgPSBsaXN0KHRpdGxlID0gJ0RyaWZ0IHJhdGUgKG0vcyknKSkpCmBgYAoKIyMjIyBpbmRfMjAxODA3MiB7LnVubGlzdGVkIC51bm51bWJlcmVkfQoKYGBge3IgZGF0YS1leHBsb3JhdGlvbi0yMDE4LTQwfQojIGluZF8yMDE4MDcyCnBsb3RfbHkoCiAgeCA9IGRhdGFQbG90Wy5pZCA9PSAiaW5kXzIwMTgwNzIiLCBiYWRsXSwKICB5ID0gZGF0YVBsb3RbLmlkID09ICJpbmRfMjAxODA3MiIsIGRheV9kZXBhcnR1cmVdLAogIHogPSBkYXRhUGxvdFsuaWQgPT0gImluZF8yMDE4MDcyIiwgZHJpZnRyYXRlXSwKICB0eXBlID0gInNjYXR0ZXIzZCIsCiAgbW9kZSA9ICJtYXJrZXJzIiwKICBtYXJrZXIgPSBsaXN0KHNpemUgPSAyKSwKICBjb2xvciA9IGRhdGFQbG90Wy5pZCA9PSAiaW5kXzIwMTgwNzIiLCBkYXlfZGVwYXJ0dXJlXQopICU+JSAKICBsYXlvdXQoc2NlbmUgPSBsaXN0KHhheGlzID0gbGlzdCh0aXRsZSA9ICdCZWhhdmlvcmFsIEFETCcpLAogICAgICAgICAgICAgICAgICAgICAgeWF4aXMgPSBsaXN0KHRpdGxlID0gJyMgZGF5cyBzaW5jZSBkZXBhcnR1cmUnKSwKICAgICAgICAgICAgICAgICAgICAgIHpheGlzID0gbGlzdCh0aXRsZSA9ICdEcmlmdCByYXRlIChtL3MpJykpKQpgYGAKCiMjIyMgaW5kXzIwMTgwNzQgey51bmxpc3RlZCAudW5udW1iZXJlZH0KCmBgYHtyIGRhdGEtZXhwbG9yYXRpb24tMjAxOC00MX0KIyBpbmRfMjAxODA3NApwbG90X2x5KAogIHggPSBkYXRhUGxvdFsuaWQgPT0gImluZF8yMDE4MDc0IiwgYmFkbF0sCiAgeSA9IGRhdGFQbG90Wy5pZCA9PSAiaW5kXzIwMTgwNzQiLCBkYXlfZGVwYXJ0dXJlXSwKICB6ID0gZGF0YVBsb3RbLmlkID09ICJpbmRfMjAxODA3NCIsIGRyaWZ0cmF0ZV0sCiAgdHlwZSA9ICJzY2F0dGVyM2QiLAogIG1vZGUgPSAibWFya2VycyIsCiAgbWFya2VyID0gbGlzdChzaXplID0gMiksCiAgY29sb3IgPSBkYXRhUGxvdFsuaWQgPT0gImluZF8yMDE4MDc0IiwgZGF5X2RlcGFydHVyZV0KKSAlPiUgCiAgbGF5b3V0KHNjZW5lID0gbGlzdCh4YXhpcyA9IGxpc3QodGl0bGUgPSAnQmVoYXZpb3JhbCBBREwnKSwKICAgICAgICAgICAgICAgICAgICAgIHlheGlzID0gbGlzdCh0aXRsZSA9ICcjIGRheXMgc2luY2UgZGVwYXJ0dXJlJyksCiAgICAgICAgICAgICAgICAgICAgICB6YXhpcyA9IGxpc3QodGl0bGUgPSAnRHJpZnQgcmF0ZSAobS9zKScpKSkKYGBgCgojIyMjIGluZF8yMDE4MDcyIHsudW5saXN0ZWQgLnVubnVtYmVyZWR9CgpgYGB7ciBkYXRhLWV4cGxvcmF0aW9uLTIwMTgtNDJ9CiMgaW5kXzIwMTgwODAKcGxvdF9seSgKICB4ID0gZGF0YVBsb3RbLmlkID09ICJpbmRfMjAxODA4MCIsIGJhZGxdLAogIHkgPSBkYXRhUGxvdFsuaWQgPT0gImluZF8yMDE4MDgwIiwgZGF5X2RlcGFydHVyZV0sCiAgeiA9IGRhdGFQbG90Wy5pZCA9PSAiaW5kXzIwMTgwODAiLCBkcmlmdHJhdGVdLAogIHR5cGUgPSAic2NhdHRlcjNkIiwKICBtb2RlID0gIm1hcmtlcnMiLAogIG1hcmtlciA9IGxpc3Qoc2l6ZSA9IDIpLAogIGNvbG9yID0gZGF0YVBsb3RbLmlkID09ICJpbmRfMjAxODA4MCIsIGRheV9kZXBhcnR1cmVdCikgJT4lIAogIGxheW91dChzY2VuZSA9IGxpc3QoeGF4aXMgPSBsaXN0KHRpdGxlID0gJ0JlaGF2aW9yYWwgQURMJyksCiAgICAgICAgICAgICAgICAgICAgICB5YXhpcyA9IGxpc3QodGl0bGUgPSAnIyBkYXlzIHNpbmNlIGRlcGFydHVyZScpLAogICAgICAgICAgICAgICAgICAgICAgemF4aXMgPSBsaXN0KHRpdGxlID0gJ0RyaWZ0IHJhdGUgKG0vcyknKSkpCmBgYAoKIyMgR1BTIGRhdGEKClNpbmNlIHRoaXMgcGFydCBpcyB0aW1lIGNvbnN1bWluZywgd2UgZGVkaWNhdGVkIGEgd2hvbGUgYXJ0aWNsZSAoYHZpZ25ldHRlKCJkYXRhX2V4cGxvcmF0aW9uXzIwMThfbWFwIilgKSB0byByZWR1Y2UgY29tcGlsYXRpb24gdGltZS4KCmBgYHtyfQojIHNhdmluZyB0aGUgZGF0YV8yMDE4X2ZpbHRlciBkYXRhc2V0CnNhdmVSRFMoZGF0YV8yMDE4X2ZpbHRlciwgZmlsZSA9ICJ0bXAvZGF0YV8yMDE4X2ZpbHRlci5yZHMiKQpgYGAKCg==